-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Allow for "Nick's Method" Style Transactions & Contract Deployments in Revive #10476
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
/cmd prdoc --audience runtime_dev --bump patch |
…time_dev --bump patch'
Differential Tests Results (PolkaVM)Specified Tests
Counts
FailuresThe test specifiers seen in this section have the format 'path::case_idx::compilation_mode' and they're compatible with the revive differential tests framework and can be specified to it directly in the same way that they're provided through the The failures are provided in an expandable section to ensure that the PR does not get polluted with information. Please click on the section below for more information Detailed Differential Tests Failure Information
|
Differential Tests Results (REVM)Specified Tests
Counts
FailuresThe test specifiers seen in this section have the format 'path::case_idx::compilation_mode' and they're compatible with the revive differential tests framework and can be specified to it directly in the same way that they're provided through the The failures are provided in an expandable section to ensure that the PR does not get polluted with information. Please click on the section below for more information Detailed Differential Tests Failure Information
|
pgherveou
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure we should allow that though I think the competitor disallow it now
can you double check it?
for example this is what I found in Geth
https://github.com/ethereum/go-ethereum/blob/6f2cbb7a27ba7e62b0bdb2090755ef0d271714be/internal/ethapi/api.go?plain=1#L1557-L1560
removing chain-id protection (for legacy tx) seems like a step backward 🤔
| } | ||
|
|
||
| #[test] | ||
| fn contract_deployment_with_nick_method_works() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of hardcoding the raw bytes, might be clearer if we build the TransactionLegacyUnsigned and then add the fake signature with with_signature
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason why I used these bytes is because they're from EIP-2470 which is a transaction that makes use of Nick's Method
| #[test] | ||
| fn dry_run_contract_deployment_with_nick_method_works() { | ||
| // Arrange | ||
| let raw_transaction_bytes = alloy_core::hex!("0xf9016c8085174876e8008303c4d88080b90154608060405234801561001057600080fd5b50610134806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80634af63f0214602d575b600080fd5b60cf60048036036040811015604157600080fd5b810190602081018135640100000000811115605b57600080fd5b820183602082011115606c57600080fd5b80359060200191846001830284011164010000000083111715608d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550509135925060eb915050565b604080516001600160a01b039092168252519081900360200190f35b6000818351602085016000f5939250505056fea26469706673582212206b44f8a82cb6b156bfcc3dc6aadd6df4eefd204bc928a4397fd15dacf6d5320564736f6c634300060200331b83247000822470"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure this test adds much, we can just keep the next one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Happy to remove it, I just wanted to check both flows to make sure that they worked.
as you mentioned seems to only be disabled at the rpc layer quickly checked other implementation, these changes seems to match what other implementation do |
|
@pgherveou pre EIP155 transactions are still supported AFAIK -> https://github.com/papermoonio/pre-eip155-hardhat (Moonbase and Sepolia). Typically, applications are recommended to switch to EIP155 transaction signing, including the actual chain ID. One option could be to include a client flag to force EIP155 check, etc. |
xermicus
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not convinced that this is a good idea and we need it. The referenced EIP is marked as stagnant (so, not live) anyways.
| // We would like to allow for transactions without a chain id to be executed through pallet | ||
| // revive. These are called unprotected transactions and they are transactions that predate | ||
| // EIP-155 which do not include a Chain ID. These transactions are still useful today in certain | ||
| // patterns in Ethereum such as "Nick's Method" for contract deployment which allows a contract | ||
| // to be deployed on all chains with the same address. This is only allowed for legacy | ||
| // transactions and isn't allowed for any other transaction type. | ||
| // * Here's a relevant EIP: https://eips.ethereum.org/EIPS/eip-2470 | ||
| // * Here's Nick's article: https://weka.medium.com/how-to-send-ether-to-11-440-people-187e332566b7 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a doc comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where would you recommend the doc comment to go? AFAIK there is no place to add a doc comment other than functions, types, etc, so there's no place that would accept a doc comment here
| // We would like to allow for transactions without a chain id to be executed through pallet | ||
| // revive. These are called unprotected transactions and they are transactions that predate | ||
| // EIP-155 which do not include a Chain ID. These transactions are still useful today in certain | ||
| // patterns in Ethereum such as "Nick's Method" for contract deployment which allows a contract | ||
| // to be deployed on all chains with the same address. This is only allowed for legacy | ||
| // transactions and isn't allowed for any other transaction type. | ||
| // * Here's a relevant EIP: https://eips.ethereum.org/EIPS/eip-2470 | ||
| // * Here's Nick's article: https://weka.medium.com/how-to-send-ether-to-11-440-people-187e332566b7 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The linked article doesn't talk about chain IDs at all. What am I missing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, Nick's method is not really talking about chain IDs at all, but for the contracts mentioned in the issue they are not using EIP2718 transaction envelope or EIP155, meaning that the contracts don't expect the chain-id as part of the RLP encode being signed.
This means that if we don't support pre-eip155 transactions (of legacy type) then we won't be able to deploy some of the contracts that use Nick's method to ensure the same address across different chains.
With type 2 transactions, the chain ID is included in the RLP encode but the v value is no longer relevant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means that if we don't support pre-eip155 transactions (of legacy type) then we won't be able to deploy some of the contracts that use Nick's method to ensure the same address across different chains.
FWIW we don't have to do this hack since we have governance on Polkadot.
I added a section in the PR doc that shows the various competitors and proof that this is allowed. Additionally, this adheres to EIP-155.
This is the RPC check I mentioned in the PR doc, you can see that it can be skipped if
It's not removed, it's only removed for legacy transactions that do not include it. |
Yup, this is a good idea and it matches what other chains do too where there is an additional check in the RPC layer that can be disabled through a flag. I added that to this PR. |
Description
This pull request allows for “Nick’s Method” 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.,
Multicall3and 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:
As mentioned in paritytech/contract-issues#225, this pattern is already being used in a number of contracts. Most notably,
Multicall3and 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 Transactionerror as seen below:polkadot-sdk/substrate/frame/revive/src/evm/call.rs
Lines 71 to 76 in c688963
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:
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” style of contract deployment. Non-legacy transaction continue to require the chain id to be provided.
Review Notes
substrate/frame/revive/src/evm/call.rsfile allowing for legacy contracts to not have the chain id set.dry_run_contract_deployment_with_nick_method_workscontract_deployment_with_nick_method_workseth_transactcall.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:
--allow-unprotected-txsflag setThe behavior of Geth when it comes to unprotected transactions is:
--rpc.allow_unprotected_txsflag 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: