Skip to content

[stable2512] Backport #10476#10737

Merged
athei merged 5 commits intostable2512from
backport-10476-to-stable2512
Jan 7, 2026
Merged

[stable2512] Backport #10476#10737
athei merged 5 commits intostable2512from
backport-10476-to-stable2512

Conversation

@paritytech-release-backport-bot
Copy link
Copy Markdown

Backport #10476 into stable2512 from 0xOmarA.

See the documentation on how to use this bot.

…n Revive (#10476)

# Description

This pull request allows for “[Nick’s
Method](https://weka.medium.com/how-to-send-ether-to-11-440-people-187e332566b7)”
style of deploying contracts which was requested in
paritytech/contract-issues#225 and was
attempted to be solved in
paritytech/contract-issues#99.

The “Nick Method” style of contract deployment is a very useful concept
to use when we wish to deploy a contract on multiple chains **with the
same address**. It allows us to do that by constructing a deployment
transaction that can be executed on any chain, thus allowing us to get
the same address for the contract’s deployment on any chain.

Additionally, this method allows for the contracts to be deployed
trustlessly, meaning that if any actor (regardless of whether they’re
honest or not) follow the same method for deploying the contract then
they’d get the same address across all chains. This allows anyone in the
Polkadot ecosystem to take existing contracts that use this method of
deployment (e.g., `Multicall3` and the ERC-1820 registry) and deploy
them on Polkadot and there’s already trust that the code is the same.

In order to be able to use the same transaction across multiple chains
transaction authors need to:

- Not include a chain id.
- Include a high gas limit so that the transaction works on (almost) all
chains.

As mentioned in
paritytech/contract-issues#225, this pattern
is already being used in a number of contracts. Most notably,
`Multicall3` and the ERC-1820 Registry.

Before this PR this method didn’t work in revive since the chain id was
an absolute must and any transaction that didn’t include a chain id
would fail with an `Invalid Transaction` error as seen below:

https://github.com/paritytech/polkadot-sdk/blob/c688963f51c55b3c2a16a00a33c4a086792a1544/substrate/frame/revive/src/evm/call.rs#L71-L76

The above implementation misses an important detail: legacy transactions
are permitted to not have the chain id set while all other non-legacy
transactions do not permit that. The models we had for legacy
transactions respected that, but we still did the chain id check for all
transaction types, which is incorrect. Therefore, this part of the code
was changed to the following:

```rust
match (tx.chain_id, tx.r#type.as_ref()) {
	(None, Some(super::Byte(TYPE_LEGACY))) => {},
	(Some(chain_id), ..) =>
		if chain_id != <T as Config>::ChainId::get().into() {
			log::debug!(target: LOG_TARGET, "Invalid chain_id {chain_id:?}");
			return Err(InvalidTransaction::Call);
		},
	(None, ..) => {
		log::debug!(target: LOG_TARGET, "Invalid chain_id None");
		return Err(InvalidTransaction::Call);
	},
}
```

The above code skips the chain id check if the transaction is of the
legacy type. Otherwise, the chain id is checked. If no chain id is
provided and the transaction is not of the legacy type then we error
out.

## Integration

Be aware that we now allow for legacy transactions to not have the chain
ID set in order to allow for “[Nick’s
Method](https://weka.medium.com/how-to-send-ether-to-11-440-people-187e332566b7)”
style of contract deployment. Non-legacy transaction continue to require
the chain id to be provided.

## Review Notes

- The main change that this PR makes can be found in the
`substrate/frame/revive/src/evm/call.rs` file allowing for legacy
contracts to not have the chain id set.
- Two new tests were added with this PR:
  - `dry_run_contract_deployment_with_nick_method_works`
  - `contract_deployment_with_nick_method_works`
- Both of the above tests test that “[Nick’s
Method](https://weka.medium.com/how-to-send-ether-to-11-440-people-187e332566b7)”
can be used to deploy the singleton factory contract provided in
[ERC-2470](https://eips.ethereum.org/EIPS/eip-2470) in a dry run and in
an `eth_transact` call.
- Note that the above tests needed to modify the transaction provided in
the ERC to update its gas limit (since the provided gas limit was too
low for our platform), **which breaks the whole idea of Nick’s Method
where the same transaction can be submitted to the same chain**. I
suspect that #10393
should fix this issue with the new gas scaling.

## Behavior On Other Chains

Since some of the comments on this PR talked about whether this is a
good idea, I wanted to add this section as justification for adding this
and also to review what other chains do with regards to unprotected
transactions.

I think that the security of this feature can be justified by:
* The fact that this feature is allowed on most other EVM chains,
including Ethereum mainnet itself.
* That metamask will fill in the chain-id automatically for users (as
seen
[here](https://docs.metamask.io/wallet/how-to/send-transactions?utm_source=chatgpt.com#chain-id)),
thus preventing users from broadcasting a re-playable transaction.
* That the default behavior of Alloy and other developer tools is to
fill in the chain ID when the developer is constructing transactions.
* That people who want to use this feature need to start their own RPC
with the `--allow-unprotected-txs` flag set

The behavior of Geth when it comes to unprotected transactions is:
* They're allowed at the protocol level for legacy transactions.
* They're disallowed at the protocol level for other transaction types.
* They're not allowed to be submitted through the Geth RPC unless the
`--rpc.allow_unprotected_txs` flag is set when Geth is started.

The above behavior matches what EIP-155 set in place for legacy
transactions.

The following is an overview of the various chains and their stance on
unprotected transactions:

* Ethereum/Geth: Allowed at the protocol level, the node must be started
with a special flag to permit it to be submitted through the RPC
([source](https://geth.ethereum.org/docs/fundamentals/command-line-options))
* Avalanche: Allowed at the protocol level, the node must be started
with a special flag to permit it to be submitted through the RPC
([source](https://build.avax.network/docs/nodes/chain-configs/subnet-evm#transaction-processing))
* Polygon: Allowed at the protocol level, the node must be started with
a special flag to permit it to be submitted through the RPC
([source](https://forum.polygon.technology/t/bor-v0-4-0-mainnet-release-indore-fork/12280))
* Arbitrum: Allowed at the protocol level, the node must be started with
a special flag to permit it to be submitted through the RPC
([source](https://pkg.go.dev/github.com/nim4/go-arbitrum/cmd/utils#:~:text=AllowUnprotectedTxs%20%3D%20%26cli.BoolFlag%7B%0A%09%09Name%3A%20%20%20%20%20%22rpc.allow%2Dunprotected%2Dtxs%22%2C%0A%09%09Usage%3A%20%20%20%20%22Allow%20for%20unprotected%20(non%20EIP155%20signed)%20transactions%20to%20be%20submitted%20via%20RPC%22%2C%0A%09%09Category%3A%20flags.APICategory%2C%0A%09%7D))

---------

Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Torsten Stüber <15174476+TorstenStueber@users.noreply.github.com>
Co-authored-by: Alexander Theißen <alex.theissen@me.com>
(cherry picked from commit 0241d9b)
@github-actions github-actions bot added the A3-backport Pull request is already reviewed well in another branch. label Jan 7, 2026
@github-actions github-actions bot requested a review from 0xOmarA January 7, 2026 05:13
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Jan 7, 2026

This pull request is amending an existing release. Please proceed with extreme caution,
as to not impact downstream teams that rely on the stability of it. Some things to consider:

  • Backports are only for 'patch' or 'minor' changes. No 'major' or other breaking change.
  • Should be a legit fix for some bug, not adding tons of new features.
  • Must either be already audited or not need an audit.
Emergency Bypass

If you really need to bypass this check: add validate: false to each crate
in the Prdoc where a breaking change is introduced. This will release a new major
version of that crate and all its reverse dependencies and basically break the release.

@EgorPopelyaev
Copy link
Copy Markdown
Contributor

@0xOmarA Hi Omar, the major bumps are usually not recommended in the backports, as they break existing stable releases. Would it be possible to change this PR so that the major bump could be downgraded to minor or patch?

@athei
Copy link
Copy Markdown
Member

athei commented Jan 7, 2026

I downgraded to minor. The change is just adding a new CLI flag. Its fine to just bump minor. It will break nobodies code.

@athei athei enabled auto-merge (squash) January 7, 2026 12:53
@athei athei merged commit 3451201 into stable2512 Jan 7, 2026
251 of 260 checks passed
@athei athei deleted the backport-10476-to-stable2512 branch January 7, 2026 13:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A3-backport Pull request is already reviewed well in another branch.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants