From 60d313b23cb89f991fd7d49da213b83d8f1748fb Mon Sep 17 00:00:00 2001 From: Csongor Kiss Date: Fri, 28 Jan 2022 13:52:54 +0000 Subject: [PATCH] ethereum: Add contract verification instructions (#792) --- clients/token_bridge/main.ts | 1 + ethereum/VERIFY.md | 57 +++++++++++++++++++++++++ ethereum/package.json | 3 +- ethereum/truffle-verify-constants.patch | 53 +++++++++++++++++++++++ 4 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 ethereum/VERIFY.md create mode 100644 ethereum/truffle-verify-constants.patch diff --git a/clients/token_bridge/main.ts b/clients/token_bridge/main.ts index d96e4320..4ccec35e 100644 --- a/clients/token_bridge/main.ts +++ b/clients/token_bridge/main.ts @@ -330,6 +330,7 @@ yargs(hideBin(process.argv)) case 2: console.log("Upgrading contract") console.log("Hash: " + (await tb.upgrade(vaa)).hash) + console.log("Don't forget to verify the new implementation! See ethereum/VERIFY.md for instructions") break default: throw new Error("unknown governance action") diff --git a/ethereum/VERIFY.md b/ethereum/VERIFY.md new file mode 100644 index 00000000..27a1637c --- /dev/null +++ b/ethereum/VERIFY.md @@ -0,0 +1,57 @@ +# Contract verification + +The various EVM explorer sites (etherscan, bscscan, etc.) support contract +verification. This essentially entails uploading the source code to the site, +and they verify that the uploaded source code compiles to the same bytecode +that's actually deployed. This enables the explorer to properly parse the +transaction payloads according to the contract ABI. + +This document outlines the process of verification. In general, you will need an +API key for the relevant explorer (this can be obtained by creating an account), +and also know which address the contract code lives. The API key is expected to +be set in the `ETHERSCAN_KEY` environment variable for all APIs (not just +etherscan, bit of a misnomer). + +Our contracts are structured as a separate proxy and an implementation. Both of +these components need to be verified, but the proxy contract only needs this +once, since it's not going to change. The implementation contract needs to be +verified each time it's upgraded. + +## Verifying the proxy contract (first time) + +The proxy contract is called `TokenBridge`. To verify it on e.g. avalanche, at contract address `0x0e082F06FF657D94310cB8cE8B0D9a04541d8052`, run + +``` +ETHERSCAN_KEY=... npm run verify --module=TokenBridge --contract_address=0x0e082F06FF657D94310cB8cE8B0D9a04541d8052 --network=avalanche +``` + +(Note: the network name comes from the `truffle-config.json`). +(Note: In this case, the `ETHERSCAN_KEY` is your snowtrace API key). + + +## Verifying the implementation contract (on each upgrade) + +To verify the actual implementation, at address `0xa321448d90d4e5b0a732867c18ea198e75cac48e`, run + +```sh +ETHERSCAN_KEY=... npm run verify --module=BridgeImplementation --contract_address=0xa321448d90d4e5b0a732867c18ea198e75cac48e --network=avalanche +``` + +As a final step, when first registering the proxy contract, we need to verify +that it's a proxy that points to the implementation we just verified. This can +be done on avalanche at +https://snowtrace.io/proxyContractChecker?a=0x0e082F06FF657D94310cB8cE8B0D9a04541d8052 + +(other evm scanner sites have an identical page). + + +# Note +The `npm run verify` script uses the `truffle-plugin-verify` plugin under the +hood. The version of `truffle-plugin-verify` pinned in the repo (`^0.5.11` at +the time of writing) doesn't support the avalanche RPC. In later versions of the +plugin, support was added, but other stuff has changed as well in the transitive +dependencies, so it fails to parse the `HDWallet` arguments in our +`truffle-config.json`. As a quick workaround, we backport the patch to `0.5.11` +by applying the `truffle-verify-constants.patch` file, which the `npm run +verify` script does transparently. Once the toolchain has been upgraded and the +errors fixed, this patch can be removed. diff --git a/ethereum/package.json b/ethereum/package.json index 60c9a853..d82c1fb5 100644 --- a/ethereum/package.json +++ b/ethereum/package.json @@ -21,7 +21,8 @@ "build": "truffle compile", "test": "mkdir -p build/contracts && cp node_modules/@openzeppelin/contracts/build/contracts/* build/contracts/ && truffle test", "migrate": "mkdir -p build/contracts && cp node_modules/@openzeppelin/contracts/build/contracts/* build/contracts/ && truffle migrate", - "flatten": "mkdir -p node_modules/@poanet/solidity-flattener/contracts && cp -r contracts/* node_modules/@poanet/solidity-flattener/contracts/ && poa-solidity-flattener" + "flatten": "mkdir -p node_modules/@poanet/solidity-flattener/contracts && cp -r contracts/* node_modules/@poanet/solidity-flattener/contracts/ && poa-solidity-flattener", + "verify": "patch -u -f node_modules/truffle-plugin-verify/constants.js -i truffle-verify-constants.patch; truffle run verify $npm_config_module@$npm_config_contract_address --network $npm_config_network" }, "author": "", "license": "ISC", diff --git a/ethereum/truffle-verify-constants.patch b/ethereum/truffle-verify-constants.patch new file mode 100644 index 00000000..fb291117 --- /dev/null +++ b/ethereum/truffle-verify-constants.patch @@ -0,0 +1,53 @@ +--- node_modules/truffle-plugin-verify/contants-old.js 2022-01-28 12:44:53.140709519 +0000 ++++ node_modules/truffle-plugin-verify/constants.js 2022-01-28 12:45:16.800710171 +0000 +@@ -3,13 +3,23 @@ + 3: 'https://api-ropsten.etherscan.io/api', + 4: 'https://api-rinkeby.etherscan.io/api', + 5: 'https://api-goerli.etherscan.io/api', ++ 10: 'https://api-optimistic.etherscan.io/api', + 42: 'https://api-kovan.etherscan.io/api', + 56: 'https://api.bscscan.com/api', ++ 69: 'https://api-kovan-optimistic.etherscan.io/api', + 97: 'https://api-testnet.bscscan.com/api', + 128: 'https://api.hecoinfo.com/api', + 137: 'https://api.polygonscan.com/api', + 250: 'https://api.ftmscan.com/api', + 256: 'https://api-testnet.hecoinfo.com/api', ++ 1284: 'https://api-moonbeam.moonscan.io/api', ++ 1285: 'https://api-moonriver.moonscan.io/api', ++ 1287: 'https://api-moonbase.moonscan.io/api', ++ 4002: 'https://api-testnet.ftmscan.com/api', ++ 42161: 'https://api.arbiscan.io/api', ++ 43113: 'https://api-testnet.snowtrace.io/api', ++ 43114: 'https://api.snowtrace.io/api', ++ 421611: 'https://api-testnet.arbiscan.io/api', + 80001: 'https://api-testnet.polygonscan.com/api' + } + +@@ -18,16 +28,25 @@ + 3: 'https://ropsten.etherscan.io/address', + 4: 'https://rinkeby.etherscan.io/address', + 5: 'https://goerli.etherscan.io/address', ++ 10: 'https://optimistic.etherscan.io/address', + 42: 'https://kovan.etherscan.io/address', + 56: 'https://bscscan.com/address', ++ 69: 'https://kovan-optimistic.etherscan.io/address', + 97: 'https://testnet.bscscan.com/address', + 128: 'https://hecoinfo.com/address', + 137: 'https://polygonscan.com/address', + 250: 'https://ftmscan.com/address', + 256: 'https://testnet.hecoinfo.com/address', ++ 1284: 'https://moonbeam.moonscan.io/address', ++ 1285: 'https://moonriver.moonscan.io/address', ++ 1287: 'https://moonbase.moonscan.io/address', ++ 4002: 'https://testnet.ftmscan.com/address', ++ 42161: 'https://arbiscan.io/address', ++ 43113: 'https://testnet.snowtrace.io/address', ++ 43114: 'https://snowtrace.io/address', ++ 421611: 'https://testnet.arbiscan.io/address', + 80001: 'https://mumbai.polygonscan.com/address' + } +- + const RequestStatus = { + OK: '1', + NOTOK: '0'