| Report Date | 2026/08/31 |
| Submitted by | Nathaniel Bajo |
@nathanielbajo:matrix.org1HXh7kCk2Z9Er4TpqF7TPX6ivSnJTECesp44RP7jnP7RCeL12026/03/12 (extrinsic)2026/05/15pallet-revive and EVM compatibilityI'm applying for Rank I retention.
Most of my time since the promotion has gone into pallet-revive, reading the EVM implementation against the Ethereum spec and revm and fixing what doesn't match. The rest went to the fellowship runtimes, clearing out finished migrations and closing gaps the Asset Hub Migration left behind. Much of what landed started as an issue I opened and diagnosed myself.
CREATE2 could deploy two contracts to one addressA contract isn't written to AccountInfoOf until its constructor frame pops, and the is_contract check in ContractInfo::new is the only thing standing between that and a duplicate deployment. Re-entrancy is on by default, so a factory could call CREATE2 twice with the same salt and code inside one transaction and see the address as empty both times. Two constructors then ran for one account, which permanently leaked a consumer reference and the code refcount and orphaned the second contract's storage deposit. EIP-684 exists to stop exactly this.
Reported in #12639, fixed in #12645 (merged 2026/07/20) by rejecting a nested instantiate whose target is already being constructed by an ancestor frame.
EXTCODECOPY trapped instead of zero fillingEXTCODECOPY converted code_offset with as_usize_or_halt, so an offset too large for a usize halted with OutOfGas where Ethereum returns zeros. The sibling copy opcodes already used as_usize_saturated, so this was an isolated slip that produced a different state root.
Reported in #12643, fixed in #12650 (merged 2026/08/14).
pallet_session sets type KeyDeposit = () on both relays, so set_keys reserved nothing and anyone could create SessionKeys entries at no cost. I reported it in runtimes#1200 and proposed wiring up the deposit.
Thanks to @sigurpol, who pushed back with a better fix. Post AHM the key lifecycle already lives on Asset Hub and is forwarded to the relay through ah_client::set_keys_from_ah, and the relay extrinsics had only been left open to give validators time to move across, so the right answer was to close them rather than price them. I reworked the PR to that approach: runtimes#1212 (merged 2026/06/29) disables set_keys and purge_keys on both relays through PostAhmFilter, with tests asserting each is rejected with CallFiltered. sigurpol also picked up the validator communication and documentation side, and @Ank4n raised the staged rollout, Kusama first and Polkadot shortly after.
pallet-revive eth-rpc)Three fixes so Ethereum tooling works against Asset Hub without special casing.
Every non ClientError variant collapsed into a blanket -32600 Invalid Request. #11887 (merged 2026/06/29) maps ConversionError to -32602 and the execution time variants to -32000, which is what Geth and Nethermind do. Reported in #11886.
eth_estimate_gas on plain transfersEvery call ran a full binary search of dry runs, including EOA to EOA transfers that always cost 21,000. #11890 (merged 2026/06/26) returns the fixed cost when there's no calldata, no code at the destination, and no access list, authorization list, blob payload or state overrides. Reported in #11888.
SubmittedTransaction::gas() panicIt unwrapped an Option<U256> that is legitimately None for legacy payloads, and it was reachable from the published crate through an ungated pub mod example. #12220 (merged 2026/07/03) returns Option<U256> instead. Reported in #11889.
pallet-state-trie-migration from the Polkadot relay and both Asset Hubs, and purged its leftover storage with a RemovePallet migration.pallet-revive weights instead of the kitchensink fallback. This was open at my last report.pallet-parameters on Collectives Polkadot so governance can maintain an allow-list of accounts, such as the Parity tip bot, that may open Fellowship referenda without holding a rank.reclaim_bounty_funds that returns funds stranded in closed bounty accounts to the treasury, free on success and paid on a no-op so it can't be griefed.This is the biggest thread I have open and it carries into the next period. The ETH RPC runs as its own binary talking to the node over subxt, which is a hop and an extra moving part that doesn't need to exist. I scoped it in #11221.
My first attempt, #11297, made the RPC server generic over its backend behind a SubstrateClientT trait. Review turned up a smaller path: subxt's Backend is sealed but RpcClientT isn't. I agreed the change of direction with the pallet-revive team and opened #12760 as the POC, keeping #11297 open as the record of how we got there.
#12760 dispatches JSON-RPC into the node's in-memory RpcModule rather than over a loopback WebSocket, behind an off by default feature. Running it against an Asset Hub Westend dev chain turned up three wiring bugs, all fixed: two nested block_on calls and a Prometheus registration panic. Review since then tightened subscription cleanup, so dropping one now calls unsub the way a real transport does.
The design works. I'm writing it up with the pallet-revive team to take to the node team.
Beyond direct code contributions, I actively identify and document gaps, edge cases, and improvements across the ecosystem to guide future work and lower the contribution barrier. This reporting period I opened a number of issues, particularly around pallet-revive, many of which I am now implementing myself: #12648, #12445 and #12352 are all open PRs against my own issues.
Some of the currently open issues I authored can be found here:
| Ranks | Activity thresholds | Agreement thresholds | Member's voting activities | Comments |
|---|---|---|---|---|
| I | 90% | N/A | I have voted on 0 out of 0 referenda in which I was eligible to vote. | |
| II | 80% | N/A | ||
| III | 70% | 100% | ||
| IV | 60% | 90% | ||
| V | 50% | 80% | ||
| VI | 40% | 70% |
Question(s):
Concern(s):
Comment(s):
Threshold