Skip to content
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

Evm safe upgrades #1272

Merged
merged 6 commits into from Jun 27, 2022
Merged

Evm safe upgrades #1272

merged 6 commits into from Jun 27, 2022

Conversation

kcsongor
Copy link
Contributor

@kcsongor kcsongor commented Jun 14, 2022

This PR implements a new test for the EVM contracts that ensures that new changes do not clobber the on-chain storage or break upgradeability. At a high level, it achieves this by simulating an upgrade of each ethereum mainnet contract (core, token bridge, nft bridge) twice. Twice, to ensure that after the upgrade, the contract is still upgradeable.

To implement this test, we need several components in place. We use anvil (from foundry) to run a fork of mainnet. ganache is not sufficient for this, because we need an RPC method to upgrade arbitrary storage slots (hardhat_setStorageAt, which is supported by hardhat and anvil). This is needed because the mainnet contracts only accept VAAs signed by the 19 guardians, and naturally we can't obtain these signatures in a test setting. Therefore, the first thing the test does is overrides the guardian set to the devnet guardian set using that RPC method. (See 5362e65#diff-fa1b92083deb8655306f5f9d48d04ff921732a7ae054c62987d471eacf77e9abR243; this requires a bunch of code for handling storage slots. Tried to make that code as reusable as possible.)

Once the guardian set is swapped out, the upgrade simulation can proceed. In order to tell whether the storage has been messed up, we need a way to query all state parameters to compare before and after the upgrade. The query_contract_evm function (5362e65#diff-fa1b92083deb8655306f5f9d48d04ff921732a7ae054c62987d471eacf77e9abR12) does this by querying all public getters of a contract. This function is exposed as part of the CLI client, for example the mainnet ethereum token bridge state can be queried by running worm evm info -c ethereum -m TokenBridge -n mainnet which yields

{
  "address": "0x3ee18B2214AFF97000D974cf647E7C347E8fa585",
  "wormhole": "0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B",
  "implementation": "0x91175AEE6dAc41B9C1f749ded077568aD93B84Ca",
  "isInitialized": true,
  "tokenImplementation": "0x61B2fcA6c3f7580c8D0d4d38AD558b247AD6c71A",
  "chainId": 2,
  "governanceChainId": 1,
  "governanceContract": "0x0000000000000000000000000000000000000000000000000000000000000004",
  "WETH": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
  "registrations": {
    "solana": "0xec7372995d5cc8732397fb0ad35c0121e0eaa90d26f828a534cab54391b3a4f5",
    "terra": "0x0000000000000000000000007cf7b764e38a0a5e967972c1df77d432510564e2",
    "bsc": "0x000000000000000000000000b6f6d86a8f9879a9c87f643768d9efc38c1da6e7",
    "polygon": "0x0000000000000000000000005a58505a96d1dbf8df91cb21b54419fc36e93fde",
    "avalanche": "0x0000000000000000000000000e082f06ff657d94310cb8ce8b0d9a04541d8052",
    "oasis": "0x0000000000000000000000005848c791e09901b40a9ef749f2a6735b418d7564",
    "algorand": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "aurora": "0x00000000000000000000000051b5123a7b0f9b2ba265f9c4c8de7d78d52f510f",
    "fantom": "0x0000000000000000000000007c9fc5741288cdfdd83ceb07f3ea7e22618d79d2",
    "karura": "0x000000000000000000000000ae9d7fe007b3327aa64a32824aaac52c42a6e624",
    "acala": "0x000000000000000000000000ae9d7fe007b3327aa64a32824aaac52c42a6e624",
    "klaytn": "0x0000000000000000000000005b08ac39eaed75c0439fc750d9fe7e1f9dd0193f",
    "celo": "0x000000000000000000000000796dff6d74f3e27060b71255fe517bfb23c93eed",
    "near": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "moonbeam": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "neon": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "terra2": "0xa463ad028fb79679cfc8ce1efba35ac0e77b35080a1abe9bebe83461f176b0a3",
    "ropsten": "0x0000000000000000000000000000000000000000000000000000000000000000"
  }
}

The actual testing script is implemented in ba42642 as a thin orchestration tool that runs anvil and uses the command line CLI to query the before state, do an upgrade, then query the after state, and diff the two. The easiest way to test it is by running make test-upgrade, which is exactly what the new CI action does.

The test scripts just build the contracts in the repo and upgrade to those. The test simulation script (https://github.com/certusone/wormhole/pull/1272/files#diff-78989f247e5f17e336f7c4c9a9d6ca68a84dbbd7e8b5d699a55ebcadfd3b2a8aR7-R19) can also be used to test upgrading to a contract address already uploaded to mainnet. This mode can be used as an additional safety check when doing actual mainnet upgrades, as the contract address can be verified to work before governance even takes place. I plan to write up more detailed instructions on that the next time we do an upgrade.

This change is Reviewable

@netlify
Copy link

netlify bot commented Jun 14, 2022

Deploy Preview for tubular-dango-1656b2 canceled.

Name Link
🔨 Latest commit db095fd
🔍 Latest deploy log https://app.netlify.com/sites/tubular-dango-1656b2/deploys/62b719ac4046d7000855a878

@netlify
Copy link

netlify bot commented Jun 14, 2022

Deploy Preview for roaring-moonbeam-aa0ca5 canceled.

Name Link
🔨 Latest commit db095fd
🔍 Latest deploy log https://app.netlify.com/sites/roaring-moonbeam-aa0ca5/deploys/62b719ac0f928800091d9d02

@kcsongor kcsongor force-pushed the evm-safe-upgrades branch 18 times, most recently from 3de6568 to b0ec15b Compare June 14, 2022 22:46
@kcsongor
Copy link
Contributor Author

@kcsongor kcsongor force-pushed the evm-safe-upgrades branch 2 times, most recently from d13c952 to fb10b34 Compare June 14, 2022 23:13
@kcsongor kcsongor force-pushed the evm-safe-upgrades branch 3 times, most recently from f96426f to bb6fab4 Compare June 25, 2022 14:16
Csongor Kiss added 3 commits June 25, 2022 15:20
* Add command to update evm storage slot
* Add command to ecrecover
* Add command to print contract addresses
* Add command to print RPC urls
* Add command to query on-chain state of EVM contracts
* Print digest in parse VAA command
@kcsongor kcsongor merged commit 0018bf7 into dev.v2 Jun 27, 2022
@kcsongor kcsongor deleted the evm-safe-upgrades branch June 27, 2022 18:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants