-
Notifications
You must be signed in to change notification settings - Fork 10
Ro - Address collision in cross - chain contract creation (breaks tooling) #204
Comments
Comment from Optimism Description: Address collision in cross - chain contract creation (breaks tooling) Reason: This is correct, but is unexpected behavior external to the scope of the code. Thus, this is a low issue. Action: Increment the nonce in the op-node to make transaction receipts use the correct nonce for contract creation on L1 -> L2 bridge. |
Escalate for 250 USDC This bug clearly breaks the specifications from Optimism. The debate here is if this is marked as a Medium or as a spec. It could be marked as medium because it breaks EVM complete equivalence (as shown below):
Here are concrete examples where this bug causes the specifications to differ: Just to recap, this issue is manifested when creating contracts from L1 -> L2. The nonce is not incremented and thus the contract created in the transaction receipt will always be the same (nonce is always 0). When creating a contract, the address is computed as follows: computed_address = keccak256(rlp.encode([address, nonce]))
canonical_address = computed_address[-20:]
padded_address = left_pad_zero_bytes(canonical_address, 20)
return Address(padded_address) If the nonce is kept at 0 during the receipt, then the new contract address will always be the same. This issue breaks the following specifications: 1:
Link: https://github.com/ethereum-optimism/optimism/blob/develop/specs/deposits.md#nonce-handling Quote: "however it maintains consistency with the use of nonces during contract creation. It may also simplify integration with downstream tooling (such as wallets and block explorers)." This issue completely breaks the integration with downstream tooling:
This is an account with code (contract) on Optimism goerli: 0x0a1c3c13c35275d030ff9fb660946cf2fca74ece But Etherscan and the rest of the block explorers display it as an EOA:
Take this transaction for example: It appears as if the contract created was "0x5d7..", while in reality it is incorrect. Note that the nonce also appears as "0". It breaks complete "EVM Equivalence" From the Optimism blog post:
Quote: "This means that — down to the very deepest depths — the existing Ethereum stack will now integrate with the L2 system, too. Every debugger. Every toolchain. Every node implementation. We believe that any L2 offering any EVM experience will have to meet this bar — anything less is unacceptable." Apart from breaking downstream tooling like block explorers and debuggers, it can also break frontend / backend applications that rely on the transaction receipt as the source of truth. For example, when the address 0x7dF608C479d2D2a7df677fEEc6f2535Eb268da01 creates a contract from L1 to L2, the contract address in the receipt will always be the same, because the nonce is kept at 0:
|
You've created a valid escalation for 250 USDC! To remove the escalation from consideration: Delete your comment. You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final. |
Escalation accepted. Comment provides sufficient evidence for a specification issue. Labeling #176 as duplicate as it describes the same issue |
This issue's escalations have been accepted! Contestants' payouts and scores will be updated according to the changes made on this issue. |
Ro
medium
Address collision in cross - chain contract creation (breaks tooling)
Summary
When creating a contract from L1 (mainnet) to L2 (optimism) the nonce of the sender is kept at 0 in the context of the transaction receipt and thus the existing infrastructure (Etherscan) will incorrectly interpret the address of the new contract (creating a collision).
Vulnerability Detail
It is possible to create a contract in Layer 2 from Layer 1 by sending a transaction to the optimism portal.
This is the function of interest:
To create a contract the "_to" address needs to be set to "address(0x0), " the "_isCreation" needs to be set to "true" and the bytecode needs to be passed in the "_data" field.
If the nonce is kept at 0 during some time of the execution, the new contract address will always be the same (nonce is always 0).
NOTE: In reality, the new contract is created with the proper nonce (and the nonce is updated), but the receipt displays it wrongly and during a point in the execution is also kept at 0 so it breaks Etherscan, Blockscout and the rest of the block exploreres.
Impact
Infrastructure tooling like Etherscan is the source of truth for most users, therefore having inconsistent data between these tools and Optimism is not recommended.
This bug causes existing tooling like Etherscan and Blockscout to display wrong data in the following ways:
See this link for reference: https://goerli-optimism.etherscan.io/address/0x5d7ee88447367b9212fa655dc863a1e83f7e189d
When the account 0x7d.. creates a new contract from Layer 1, the address "0x5d.." will always appear as the new contract created.
See this address on etherscan goerli optimism:
https://goerli-optimism.etherscan.io/address/0x0a1c3c13c35275d030ff9fb660946cf2fca74ece
It appears to be a regular EOA, while in reality, it is a contract.
Run the following command to verify:
cast code 0x0a1c3c13c35275d030ff9fb660946cf2fca74ece --rpc-url https://goerli.optimism.io
Code Snippet
https://github.com/sherlock-audit/2023-01-optimism/blob/main/optimism/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol#L358
Tool used
Manual Review
Recommendation
The nonce should be set to the sender's nonce from the op-node.
The text was updated successfully, but these errors were encountered: