Skip to content

Commit

Permalink
Adds VAA self signing logic and updates implementation addresses (#42)
Browse files Browse the repository at this point in the history
* evm: remove obsolete packages.

* evm: fixes shebang for shell scripts.

* evm: forward arguments in deploy shell scripts.

* evm: adjustments in `tsconfig.json`

* evm: adds script to self sign testnet upgrade.

* evm: yarn.lock update

* evm: Adds registrations to circle integration initializer temporarily.

* evm: fixes env var for RPC URLs

* evm: rename environment files.

* evm: adds RPC URLs for arbitrum and eth testnets

* evm: updates the CircleIntegration implementation addresses.

* evm: switches to ESM.

* evm: yarn.lock update

* evm: reverts testnet hardcoded cross registrations.

* evm: removes `ts-node` in favour of `tsx`

* minor fixes to submit_testnet_registraion script

* adds base deployment configuration

* fix env variable on base mainnet deployment

* base mainnet configuration

---------

Co-authored-by: solanoe <[email protected]>
  • Loading branch information
scnale and solanoepalacio authored Oct 27, 2023
1 parent 2e0831c commit 105ad59
Show file tree
Hide file tree
Showing 33 changed files with 1,649 additions and 1,238 deletions.
2 changes: 1 addition & 1 deletion evm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Then run the following command to deploy (and set up) the proxy contract:

```
# sample deployment command
. env/put_your_env_file_here.env && PRIVATE_KEY=put_your_private_key_here bash shell-scripts/deploy_contracts.sh
. env/put_your_env_file_here.env && shell-scripts/deploy_contracts.sh --private-key put_your_private_key_here
```

## Test Suite
Expand Down
File renamed without changes.
14 changes: 14 additions & 0 deletions evm/env/mainnet/base.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export CONFIGURE_CCTP_RPC="https://base.publicnode.com"

### Contract addresses
export RELEASE_WORMHOLE_ADDRESS=0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6
export RELEASE_CIRCLE_BRIDGE_ADDRESS=0x1682Ae6375C4E4A97e4B583BC394c861A46D8962 # token messenger
export RELEASE_WORMHOLE_FINALITY=1

### Deployed Circle Integration addresses
export CIRCLE_INTEGRATION_IMPLEMENTATION="0x2703483B1a5a7c577e8680de9Df8Be03c6f30e3c"
export CIRCLE_INTEGRATION_SETUP="0xD73aFD826D6bDD4D2fEF326DF5091451A5d8130a"
export CIRCLE_INTEGRATION_PROXY="0x03faBB06Fa052557143dC28eFCFc63FC12843f1D"

# Used in verification scripts
export RELEASE_EVM_CHAIN_ID=8453
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
export RPC=""
export CONFIGURE_CCTP_RPC="https://goerli-rollup.arbitrum.io/rpc"

### Contract addresses
export RELEASE_WORMHOLE_ADDRESS=0xC7A204bDBFe983FCD8d8E61D02b475D4073fF97e
export RELEASE_CIRCLE_BRIDGE_ADDRESS=0x12dcfd3fe2e9eac2859fd1ed86d2ab8c5a2f9352
export RELEASE_WORMHOLE_FINALITY=1

### Deployed Circle Integration addresses
export CIRCLE_INTEGRATION_IMPLEMENTATION=0xa098368aaadc0fdf3e309cda710d7a5f8bdeecd9
export CIRCLE_INTEGRATION_IMPLEMENTATION=0xD73aFD826D6bDD4D2fEF326DF5091451A5d8130a
export CIRCLE_INTEGRATION_SETUP=0xb0a9feeaf74f2e8e2966bf774466ca3575ec8a6d
export CIRCLE_INTEGRATION_PROXY=0x2E8F5E00a9C5D450A72700546B89E2b70DfB00f2

Expand Down
4 changes: 2 additions & 2 deletions evm/env/testnet/avax-testnet.env → evm/env/testnet/avax.env
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
export RPC="https://api.avax-test.network/ext/bc/C/rpc"
export CONFIGURE_CCTP_RPC="https://api.avax-test.network/ext/bc/C/rpc"

### Contract addresses
export RELEASE_WORMHOLE_ADDRESS=0x7bbcE28e64B3F8b84d876Ab298393c38ad7aac4C
export RELEASE_CIRCLE_BRIDGE_ADDRESS=0xeb08f243e5d3fcff26a9e38ae5520a669f4019d0
export RELEASE_WORMHOLE_FINALITY=1

### Deployed Circle Integration addresses
export CIRCLE_INTEGRATION_IMPLEMENTATION=0xf0ff9898918351148ffd97c7ddb412086505eae1
export CIRCLE_INTEGRATION_IMPLEMENTATION=0xD73aFD826D6bDD4D2fEF326DF5091451A5d8130a
export CIRCLE_INTEGRATION_SETUP=0xd66a83c1cd3cf85a071daa6a4bcbea32e22931c0
export CIRCLE_INTEGRATION_PROXY=0x58f4c17449c90665891c42e14d34aae7a26a472e

Expand Down
15 changes: 15 additions & 0 deletions evm/env/testnet/base.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export CONFIGURE_CCTP_RPC="https://goerli.base.org"

### Contract addresses
export RELEASE_WORMHOLE_ADDRESS=0x23908A62110e21C04F3A4e011d24F901F911744A
export RELEASE_CIRCLE_BRIDGE_ADDRESS=0x877b8e8c9e2383077809787ED6F279ce01CB4cc8
export RELEASE_WORMHOLE_FINALITY=1


### Deployed Circle Integration addresses
export CIRCLE_INTEGRATION_IMPLEMENTATION=0xD73aFD826D6bDD4D2fEF326DF5091451A5d8130a
export CIRCLE_INTEGRATION_SETUP=0xC5180b274Ead8aC34131B6dDa0323e403d671De7
export CIRCLE_INTEGRATION_PROXY=0x2703483B1a5a7c577e8680de9Df8Be03c6f30e3c

# Used in verification scripts
export RELEASE_EVM_CHAIN_ID=84531
4 changes: 2 additions & 2 deletions evm/env/testnet/eth-testnet.env → evm/env/testnet/eth.env
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
export RPC=""
export CONFIGURE_CCTP_RPC="https://rpc.ankr.com/eth_goerli"

### Contract addresses
export RELEASE_WORMHOLE_ADDRESS=0x706abc4E45D419950511e474C7B9Ed348A4a716c
export RELEASE_CIRCLE_BRIDGE_ADDRESS=0xd0c3da58f55358142b8d3e06c1c30c5c6114efe8
export RELEASE_WORMHOLE_FINALITY=200

### Deployed Circle Integration addresses
export CIRCLE_INTEGRATION_IMPLEMENTATION=0x4fa4b2c3744b29D0e4F1AaFE8B758F953FaCf1A4
export CIRCLE_INTEGRATION_IMPLEMENTATION=0xD73aFD826D6bDD4D2fEF326DF5091451A5d8130a
export CIRCLE_INTEGRATION_SETUP=0xB9aCd3891EBf91EC09cfe337EE5A8EEfF4317846
export CIRCLE_INTEGRATION_PROXY=0x0a69146716b3a21622287efa1607424c663069a4

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
export RPC="https://goerli.optimism.io"
export CONFIGURE_CCTP_RPC="https://rpc.goerli.optimism.gateway.fm"

### Contract addresses
export RELEASE_WORMHOLE_ADDRESS=0x6b9C8671cdDC8dEab9c719bB87cBd3e782bA6a35
export RELEASE_CIRCLE_BRIDGE_ADDRESS=0x23a04d5935ed8bc8e3eb78db3541f0abfb001c6e
export RELEASE_WORMHOLE_FINALITY=1


### Deployed Circle Integration addresses
export CIRCLE_INTEGRATION_IMPLEMENTATION=0xD73aFD826D6bDD4D2fEF326DF5091451A5d8130a
export CIRCLE_INTEGRATION_IMPLEMENTATION=0xD4Bab83eDe934973d22f1da04819fe2E5b5a9Ef4
export CIRCLE_INTEGRATION_SETUP=0xC5180b274Ead8aC34131B6dDa0323e403d671De7
export CIRCLE_INTEGRATION_PROXY=0x2703483B1a5a7c577e8680de9Df8Be03c6f30e3c

Expand Down
33 changes: 16 additions & 17 deletions evm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,28 @@
"version": "0.1.0",
"main": "index.js",
"license": "ISC",
"type": "module",
"devDependencies": {
"@types/node": "^18.11.17",
"@types/chai": "^4.3.3",
"@types/mocha": "^9.1.1",
"@types/node": "^20.0.0",
"@types/yargs": "^17.0.24",
"chai": "^4.3.6",
"ethers": "^5.7.1"
"mocha": "^10.0.0",
"ts-mocha": "^10.0.0",
"tsx": "^3.13.0",
"typescript": "^5.2.2"
},
"dependencies": {
"@certusone/wormhole-sdk": "^0.9.0",
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
"@certusone/wormhole-sdk": "^0.10.3",
"@noble/secp256k1": "^2.0.0",
"@openzeppelin/contracts": "^4.7.3",
"@typechain/ethers-v5": "^10.1.1",
"@types/argparse": "^2.0.10",
"@types/chai": "^4.3.3",
"@types/mocha": "^9.1.1",
"argparse": "^2.0.1",
"axios": "^1.1.3",
"@typechain/ethers-v5": "^11.1.1",
"@xlabs-xyz/ledger-signer": "0.0.3",
"dotenv": "^16.0.3",
"elliptic": "^6.5.4",
"express": "^4.18.2",
"mocha": "^10.0.0",
"ts-mocha": "^10.0.0",
"ts-node": "^10.9.1",
"typechain": "^8.1.1",
"typescript": "^4.8.3"
"ethers": "^5.7.1",
"typechain": "^8.3.1",
"yargs": "^17.7.2"
},
"scripts": {
"build-types": "bash shell-scripts/make_ethers_types.sh",
Expand Down
7 changes: 3 additions & 4 deletions evm/shell-scripts/deploy_contracts.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#!/bin/bash
#!/usr/bin/env bash

forge script $(dirname $0)/../forge-scripts/deploy_contracts.sol \
--rpc-url $RPC \
--private-key $PRIVATE_KEY \
--broadcast --slow
--rpc-url $CONFIGURE_CCTP_RPC \
--broadcast --slow $@
7 changes: 3 additions & 4 deletions evm/shell-scripts/deploy_implementation_only.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
#!/bin/bash
#!/usr/bin/env bash

set -euo pipefail

forge script $(dirname $0)/../forge-scripts/deploy_implementation_only.sol \
-vv \
--rpc-url $RPC \
--private-key $PRIVATE_KEY \
--broadcast --slow
--rpc-url $CONFIGURE_CCTP_RPC \
--broadcast --slow $@
4 changes: 2 additions & 2 deletions evm/shell-scripts/make_ethers_types.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash
#!/usr/bin/env bash

SRC=$(dirname $0)/../out
DST=$(dirname $0)/../ts/src/ethers-contracts

typechain --target=ethers-v5 --out-dir=$DST $SRC/*/*.json
typechain --target=ethers-v5 --node16-modules --out-dir=$DST $SRC/*/*.json
2 changes: 1 addition & 1 deletion evm/shell-scripts/run_integration_tests.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#/bin/bash
#!/usr/bin/env bash

pgrep anvil > /dev/null
if [ $? -eq 0 ]; then
Expand Down
13 changes: 8 additions & 5 deletions evm/shell-scripts/submit_testnet_registration.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/bin/bash
#!/usr/bin/env bash

# Usage: ./submit_testnet_registration <target chain> <foreign chain> <foreign emitter> <foreign domain> <forge script args (keys)>

set -euo pipefail

Expand All @@ -8,8 +10,9 @@ export FOREIGN_EMITTER=$3
export FOREIGN_DOMAIN=$4
export SIGNER_KEY=$5

forge script $(dirname $0)/../forge-scripts/generate_registration_vaa.sol \
shift 5 # <- remove 5 first arguments

forge script $(dirname $0)/../forge-scripts/submit_testnet_registration.sol \
-vv \
--rpc-url $RPC \
--private-key $PRIVATE_KEY \
--broadcast --slow
--rpc-url $CONFIGURE_CCTP_RPC \
--broadcast --slow $@
4 changes: 2 additions & 2 deletions evm/shell-scripts/upgrade_proxy.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
#!/usr/bin/env bash

set -euo pipefail

ts-node $(dirname $0)/../ts/scripts/upgrade_proxy.ts $@
npx tsx $(dirname $0)/../ts/scripts/upgrade_proxy.ts $@
2 changes: 1 addition & 1 deletion evm/shell-scripts/verify_implementation.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#/usr/bin/env bash
#!/usr/bin/env bash

etherscan_key=$1

Expand Down
2 changes: 1 addition & 1 deletion evm/shell-scripts/verify_proxy.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#/usr/bin/env bash
#!/usr/bin/env bash

etherscan_key=$1

Expand Down
2 changes: 1 addition & 1 deletion evm/shell-scripts/verify_setup.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#/usr/bin/env bash
#!/usr/bin/env bash

etherscan_key=$1

Expand Down
6 changes: 3 additions & 3 deletions evm/ts/scripts/contract_governance.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {ethers} from "ethers";
import {tryNativeToUint8Array} from "@certusone/wormhole-sdk";
import {MockGuardians} from "@certusone/wormhole-sdk/lib/cjs/mock";
import {CircleGovernanceEmitter} from "../test/helpers/mock";
import {MockGuardians} from "@certusone/wormhole-sdk/lib/esm/mock";
import {CircleGovernanceEmitter} from "../test/helpers/mock.js";
import {abi as WORMHOLE_ABI} from "../../out/IWormhole.sol/IWormhole.json";
import {abi as CIRCLE_INTEGRATION_ABI} from "../../out/CircleIntegration.sol/CircleIntegration.json";
import {getTimeNow} from "../test/helpers/utils";
import {getTimeNow} from "../test/helpers/utils.js";
import {expect} from "chai";

require("dotenv").config({path: process.argv.slice(2)[0]});
Expand Down
120 changes: 120 additions & 0 deletions evm/ts/scripts/sign_vaa.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { ethers } from "ethers";
import { tryNativeToHexString } from "@certusone/wormhole-sdk";
import { signAsync } from "@noble/secp256k1";

const circleIntegrationModule =
"0x000000000000000000000000000000436972636c65496e746567726174696f6e";
const GOVERNANCE_UPGRADE_ACTION = 3;
const governanceChainId = 1;
const governanceContract =
"0x0000000000000000000000000000000000000000000000000000000000000004";

export interface Guardian {
/**
* Private key in hexadecimal string 0x encoded.
*/
key: string;
/**
* Index of the public key in the current Guardian set.
*/
index: number;
}

export interface GuardianSet {
guardians: Guardian[];
id: number;
}

export function doubleKeccak256(body: ethers.BytesLike) {
return ethers.utils.keccak256(ethers.utils.keccak256(body));
}

export function createCircleIntegrationUpgradeVAA(
chainId: number,
newAddress: string,
guardianSet: GuardianSet,
) {
/*
bytes32 module;
uint8 action;
uint16 chain;
bytes32 newContract; //listed as address in the struct, but is actually bytes32 inside the VAA
*/

const payload = ethers.utils.solidityPack(
["bytes32", "uint8", "uint16", "bytes32"],
[
circleIntegrationModule,
GOVERNANCE_UPGRADE_ACTION,
chainId,
"0x" + tryNativeToHexString(newAddress, "ethereum"),
],
);

return encodeAndSignGovernancePayload(payload, guardianSet);
}

export async function encodeAndSignGovernancePayload(
payload: string,
guardianSet: GuardianSet,
): Promise<string> {
const timestamp = Math.floor(Date.now() / 1000);
const nonce = 1;
const sequence = 1;
const consistencyLevel = 1;
const vaaVersion = 1;

const encodedVAABody = ethers.utils.solidityPack(
["uint32", "uint32", "uint16", "bytes32", "uint64", "uint8", "bytes"],
[
timestamp,
nonce,
governanceChainId,
governanceContract,
sequence,
consistencyLevel,
payload,
],
);

const hash = doubleKeccak256(encodedVAABody).substring(2);

const signatures = (await Promise.all(guardianSet.guardians
.map(async ({ key, index }) => {
const signature = await signAsync(hash, key);
if (signature.recovery === undefined)
throw new Error(`Failed to sign message: missing recovery id`);

// Remember that each signature is accompanied by the guardian index.
const packSig = ethers.utils.solidityPack(
["uint8", "bytes32", "bytes32", "uint8"],
[
index,
ethers.utils.hexZeroPad(ethers.utils.hexlify(signature.r), 32),
ethers.utils.hexZeroPad(ethers.utils.hexlify(signature.s), 32),
signature.recovery,
],
);
return packSig.substring(2);
})))
.join("");

const vm = [
ethers.utils
.solidityPack(
["uint8", "uint32", "uint8"],
[
vaaVersion,
// guardianSetIndex
guardianSet.id,
// number of signers
guardianSet.guardians.length,
],
)
.substring(2),
signatures,
encodedVAABody.substring(2),
].join("");

return "0x" + vm;
}
Loading

0 comments on commit 105ad59

Please sign in to comment.