aptos: tooling for mainnet upgrades (#3338)
* aptos: update upgrade script to support mainnet Also factor out named_addresses into a separate helper script * scripts: aptos support for gov proposal generation * sdk/js: add aptos nft_bridge mainnet address
This commit is contained in:
parent
e71c4776ee
commit
3adce639fa
|
@ -11,21 +11,17 @@ EOF
|
|||
exit 1
|
||||
}
|
||||
|
||||
# cd to script directory so that we can run this script from anywhere
|
||||
cd "$(dirname "$0")"
|
||||
NETWORK=$1 || usage
|
||||
|
||||
if [ "$NETWORK" = mainnet ]; then
|
||||
DEPLOYER_ADDR=0x0108bc32f7de18a5f6e1e7d6ee7aff9f5fc858d0d87ac0da94dd8d2a5d267d6b
|
||||
|
||||
GUARDIAN_ADDR=0x58CC3AE5C097b213cE3c81979e1B9f9570746AA5
|
||||
|
||||
elif [ "$NETWORK" = testnet ]; then
|
||||
DEPLOYER_ADDR=0x0108bc32f7de18a5f6e1e7d6ee7aff9f5fc858d0d87ac0da94dd8d2a5d267d6b
|
||||
|
||||
GUARDIAN_ADDR=0x13947Bd48b18E53fdAeEe77F3473391aC727C638
|
||||
|
||||
elif [ "$NETWORK" = devnet ]; then
|
||||
DEPLOYER_ADDR=0x277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b
|
||||
|
||||
DOTENV=$(dirname $0)/../.env
|
||||
[[ -f "$DOTENV" ]] && . "$DOTENV"
|
||||
|
||||
|
@ -36,28 +32,28 @@ else
|
|||
usage
|
||||
fi
|
||||
|
||||
WORMHOLE_ADDR=$(worm info contract "$NETWORK" aptos Core)
|
||||
TOKEN_BRIDGE_ADDR=$(worm info contract "$NETWORK" aptos TokenBridge)
|
||||
NFT_BRIDGE_ADDR=$(worm info contract "$NETWORK" aptos NFTBridge)
|
||||
NAMED_ADDRS="wormhole=$WORMHOLE_ADDR,deployer=$DEPLOYER_ADDR,token_bridge=$TOKEN_BRIDGE_ADDR"
|
||||
NAMED_ADDRS="$(./named_addresses $NETWORK)"
|
||||
|
||||
NAMED_ADDRS="wormhole=$WORMHOLE_ADDR,deployer=$DEPLOYER_ADDR,token_bridge=$TOKEN_BRIDGE_ADDR,nft_bridge=$NFT_BRIDGE_ADDR"
|
||||
echo "Addresses: $NAMED_ADDRS"
|
||||
|
||||
# NOTE: this always succeeds, even if the deployer contact is already deployed
|
||||
echo "[1/6] Deploying deployer contract for creating resource accounts..."
|
||||
worm aptos deploy --network "$NETWORK" ../deployer --named-addresses "$NAMED_ADDRS"
|
||||
|
||||
echo "[2/6] Deploying wormhole contract at $WORMHOLE_ADDR..."
|
||||
echo "[2/6] Deploying wormhole contract..."
|
||||
worm aptos deploy-resource wormhole --network "$NETWORK" ../wormhole --named-addresses "$NAMED_ADDRS"
|
||||
|
||||
echo "[3/6] Initialising wormhole with guardian(s) $GUARDIAN_ADDR..."
|
||||
worm aptos init-wormhole --network "$NETWORK" -g $GUARDIAN_ADDR
|
||||
|
||||
echo "[4/6] Deploying token bridge contract at $TOKEN_BRIDGE_ADDR..."
|
||||
echo "[4/6] Deploying token bridge contract..."
|
||||
worm aptos deploy-resource token_bridge --network "$NETWORK" ../token_bridge --named-addresses "$NAMED_ADDRS"
|
||||
|
||||
echo "[5/6] Initialising token bridge..."
|
||||
worm aptos init-token-bridge --network "$NETWORK"
|
||||
|
||||
echo "[6/6] Deploying (& initialising) NFT bridge contract at $NFT_BRIDGE_ADDR..."
|
||||
echo "[6/6] Deploying (& initialising) NFT bridge contract..."
|
||||
worm aptos deploy-resource nft_bridge --network "$NETWORK" ../nft_bridge --named-addresses "$NAMED_ADDRS"
|
||||
|
||||
if [ "$NETWORK" = devnet ]; then
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<-EOF >&2
|
||||
Usage: ${0##*/} <network>
|
||||
|
||||
Print the named addresses for the given network.
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ $# -lt 1 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
NETWORK="$1"
|
||||
|
||||
case "$NETWORK" in
|
||||
testnet)
|
||||
DEPLOYER=0x0108bc32f7de18a5f6e1e7d6ee7aff9f5fc858d0d87ac0da94dd8d2a5d267d6b
|
||||
;;
|
||||
devnet)
|
||||
DEPLOYER=0x277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b
|
||||
;;
|
||||
mainnet)
|
||||
DEPLOYER=0x0108bc32f7de18a5f6e1e7d6ee7aff9f5fc858d0d87ac0da94dd8d2a5d267d6b
|
||||
;;
|
||||
*)
|
||||
echo "Unknown network $NETWORK" >&2
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
WORMHOLE=$(worm info contract "$NETWORK" aptos Core)
|
||||
TOKEN_BRIDGE=$(worm info contract "$NETWORK" aptos TokenBridge)
|
||||
NFT_BRIDGE=$(worm info contract "$NETWORK" aptos NFTBridge)
|
||||
|
||||
NAMED_ADDRS="wormhole=$WORMHOLE,deployer=$DEPLOYER,token_bridge=$TOKEN_BRIDGE,nft_bridge=$NFT_BRIDGE"
|
||||
|
||||
echo "$NAMED_ADDRS"
|
|
@ -1,56 +1,156 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This is a script for upgrading contracts on the Aptos network.
|
||||
# It supports all of devnet (localhost), testnet, and mainnet.
|
||||
#
|
||||
# A VAA may be provided, in which case the script uses that.
|
||||
# Otherwise, in devnet, it generates a VAA using the devnet guardian secret.
|
||||
# In testnet, it generates a VAA using the testnet guardian secret as long as
|
||||
# it's set in the environment variable GUARDIAN_SECRET.
|
||||
# In mainnet, a VAA is required.
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
function usage() {
|
||||
cat <<EOF >&2
|
||||
Usage:
|
||||
usage() {
|
||||
cat <<-EOF >&2
|
||||
Usage: ${0##*/} <network> <module> [OPTIONS]
|
||||
|
||||
$(basename "$0") <devnet|testnet> <Core|TokenBridge> -- Perform a contract upgrade
|
||||
Perform a contract upgrade.
|
||||
|
||||
Positional arguments:
|
||||
<network> Network to deploy to (devnet, testnet, mainnet)
|
||||
<module> Module to upgrade (Core, TokenBridge, NFTBridge)
|
||||
|
||||
Options:
|
||||
--vaa VAA to submit (required for mainnet)
|
||||
--yes Skip confirmation prompt
|
||||
EOF
|
||||
exit 1
|
||||
exit 1
|
||||
}
|
||||
|
||||
NETWORK=$1 || usage
|
||||
MODULE=$2 || usage
|
||||
# cd to script directory so that we can run this script from anywhere
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
if [ "$NETWORK" = testnet ]; then
|
||||
# This script upgrades the core bridge in local devnet by generating a
|
||||
# governance VAA and submitting it
|
||||
|
||||
DEPLOYER_ADDR=0x0108bc32f7de18a5f6e1e7d6ee7aff9f5fc858d0d87ac0da94dd8d2a5d267d6b
|
||||
[ -z "$GUARDIAN_SECRET" ] && echo "GUARDIAN_SECRET unset" >&2 && exit 1
|
||||
|
||||
elif [ "$NETWORK" = devnet ]; then
|
||||
GUARDIAN_SECRET=cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
|
||||
DEPLOYER_ADDR=0x277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b
|
||||
else
|
||||
usage
|
||||
# Check if the jq binary is available.
|
||||
if ! command -v jq >/dev/null; then
|
||||
echo "jq not found, please install it"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
WORMHOLE_ADDR=$(worm info contract "$NETWORK" aptos Core)
|
||||
TOKEN_BRIDGE_ADDR=$(worm info contract "$NETWORK" aptos TokenBridge)
|
||||
NFT_BRIDGE_ADDR=$(worm info contract "$NETWORK" aptos NFTBridge)
|
||||
# If positional args are missing, print help message and exit
|
||||
if [ $# -lt 2 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
NAMED_ADDRS="wormhole=$WORMHOLE_ADDR,deployer=$DEPLOYER_ADDR,token_bridge=$TOKEN_BRIDGE_ADDR,nft_bridge=$NFT_BRIDGE_ADDR"
|
||||
# Get positional arguments
|
||||
NETWORK="$1"
|
||||
shift
|
||||
MODULE="$1"
|
||||
shift
|
||||
|
||||
yes=false
|
||||
|
||||
# Parse options
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--vaa)
|
||||
VAA="$2"
|
||||
shift 2
|
||||
;;
|
||||
--yes)
|
||||
yes=true
|
||||
shift
|
||||
;;
|
||||
--) # end of options
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-*)
|
||||
echo "Error: Unsupported option $1" >&2
|
||||
usage
|
||||
;;
|
||||
*) # anything else
|
||||
echo "Error: Unsupported argument $1" >&2
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$MODULE" in
|
||||
Core)
|
||||
DIR="../wormhole"
|
||||
LOWER_MODULE="wormhole"
|
||||
;;
|
||||
TokenBridge)
|
||||
DIR="../token_bridge"
|
||||
LOWER_MODULE="token_bridge"
|
||||
;;
|
||||
NFTBridge)
|
||||
DIR="../nft_bridge"
|
||||
LOWER_MODULE="nft_bridge"
|
||||
;;
|
||||
*) echo "unsupported module $MODULE" >&2
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
NAMED_ADDRS="$(./named_addresses $NETWORK)"
|
||||
HASH=$(worm aptos hash-contracts $DIR --named-addresses "$NAMED_ADDRS")
|
||||
VAA=$(worm generate upgrade -c aptos -a "$HASH" -m "$MODULE" -g $GUARDIAN_SECRET)
|
||||
|
||||
if [ "$NETWORK" = testnet ]; then
|
||||
[ -z "$GUARDIAN_SECRET" ] && echo "GUARDIAN_SECRET unset" >&2 && exit 1
|
||||
|
||||
elif [ "$NETWORK" = devnet ]; then
|
||||
GUARDIAN_SECRET=cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
|
||||
|
||||
elif [ "$NETWORK" = mainnet ]; then
|
||||
# VAA is required for mainnet
|
||||
if [ -z "$VAA" ]; then
|
||||
echo "VAA required for mainnet. Pass it in with the --vaa flag." >&2
|
||||
echo "To generate a draft governance proposal, run" >&2
|
||||
echo " ../../scripts/contract-upgrade-governance.sh -c aptos --address $HASH --module $LOWER_MODULE" >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
usage
|
||||
fi
|
||||
|
||||
# if VAA is not set, generate it
|
||||
[ -z "$VAA" ] && VAA=$(worm generate upgrade -c aptos -a "$HASH" -m "$MODULE" -g $GUARDIAN_SECRET)
|
||||
|
||||
# parse VAA
|
||||
VAA_JSON=$(worm parse "$VAA")
|
||||
|
||||
# sanity check VAA
|
||||
check_payload_value() {
|
||||
key="$1"
|
||||
expected_value="$2"
|
||||
|
||||
payload_value=$(echo "$VAA_JSON" | jq -r ".payload.$key")
|
||||
|
||||
if [ "$payload_value" != "$expected_value" ]; then
|
||||
echo "VAA payload: expected $key $expected_value, got $payload_value" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# here we make sure the VAA is for the hash we expect
|
||||
check_payload_value "type" "ContractUpgrade"
|
||||
check_payload_value "chain" "$(worm info chain-id aptos)"
|
||||
check_payload_value "module" "$MODULE"
|
||||
check_payload_value "address" "0x$HASH"
|
||||
|
||||
echo "VAA is a valid ContractUpgrade VAA for $MODULE"
|
||||
|
||||
# Ask for confirmation
|
||||
if [ "$yes" = false ]; then
|
||||
read -p "Upgrade $MODULE to $HASH? [y/N] " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Aborting"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Submitting VAA: $VAA"
|
||||
|
||||
|
@ -59,3 +159,8 @@ CONTRACT_ADDR=$(worm info contract "$NETWORK" aptos "$MODULE")
|
|||
worm submit --network "$NETWORK" "$VAA" --contract-address "$CONTRACT_ADDR"
|
||||
worm aptos upgrade $DIR --network "$NETWORK" --contract-address "$CONTRACT_ADDR" --named-addresses "$NAMED_ADDRS"
|
||||
worm aptos migrate --network "$NETWORK" --contract-address "$CONTRACT_ADDR"
|
||||
|
||||
echo "Successfully upgraded $MODULE to $HASH"
|
||||
# if network is mainnet or testnet, print explorer link
|
||||
[ "$NETWORK" = mainnet ] || [ "$NETWORK" = testnet ] &&
|
||||
echo "Check it out at https://explorer.aptoslabs.com/account/$CONTRACT_ADDR?network=$NETWORK"
|
||||
|
|
|
@ -28,20 +28,22 @@
|
|||
|
||||
set -euo pipefail
|
||||
|
||||
function usage() {
|
||||
cat <<EOF >&2
|
||||
Usage:
|
||||
usage() {
|
||||
cat <<-EOF >&2
|
||||
Usage: $(basename "$0") [OPTIONS]
|
||||
|
||||
$(basename "$0") [-h] [-m s] [-c s] [-a s] [-o d] -- Generate governance proposal for a given module to be upgraded to a given address
|
||||
Generate governance proposal for a module to be upgraded to a given address.
|
||||
|
||||
Options:
|
||||
-h, --help Show this help message
|
||||
-m, --module <module> Specify the module (bridge, token_bridge, nft_bridge)
|
||||
-c, --chain <chain_name> Specify the chain name
|
||||
-a, --address <address> Specify the new code address (e.g., 0x3f1a6729bb27350748f0a0bd85ca641a100bf0a1)
|
||||
-o, --output <output_dir> Specify the multi-mode output directory
|
||||
-f, --force Force: bypass dirty git repo check
|
||||
|
||||
where:
|
||||
-h show this help text
|
||||
-m module (bridge, token_bridge, nft_bridge)
|
||||
-c chain name
|
||||
-a new code address (example: 0x3f1a6729bb27350748f0a0bd85ca641a100bf0a1)
|
||||
-o multi-mode output directory
|
||||
EOF
|
||||
exit 1
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check if guardiand command exists. It's needed for generating the protoxt and
|
||||
|
@ -51,39 +53,74 @@ if ! command -v guardiand >/dev/null 2>&1; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# Check if the worm command exists. It's needed for computing the digest.
|
||||
if ! command -v worm >/dev/null 2>&1; then
|
||||
echo "ERROR: worm binary not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
### Parse command line options
|
||||
address=""
|
||||
module=""
|
||||
chain_name=""
|
||||
multi_mode=false
|
||||
out_dir=""
|
||||
while getopts ':hm:c:a:o:' option; do
|
||||
case "$option" in
|
||||
h) usage
|
||||
;;
|
||||
m) module=$OPTARG
|
||||
;;
|
||||
c) chain_name=$OPTARG
|
||||
;;
|
||||
a) address=$OPTARG
|
||||
;;
|
||||
o) multi_mode=true
|
||||
out_dir=$OPTARG
|
||||
;;
|
||||
:) printf "missing argument for -%s\n" "$OPTARG" >&2
|
||||
usage
|
||||
;;
|
||||
\?) printf "illegal option: -%s\n" "$OPTARG" >&2
|
||||
usage
|
||||
;;
|
||||
allow_dirty=false
|
||||
|
||||
while (( "$#" )); do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
usage
|
||||
;;
|
||||
-m|--module)
|
||||
module="$2"
|
||||
shift 2
|
||||
;;
|
||||
-c|--chain)
|
||||
chain_name="$2"
|
||||
shift 2
|
||||
;;
|
||||
-a|--address)
|
||||
address="$2"
|
||||
shift 2
|
||||
;;
|
||||
-o|--output)
|
||||
multi_mode=true
|
||||
out_dir="$2"
|
||||
shift 2
|
||||
;;
|
||||
-f|--force)
|
||||
allow_dirty=true
|
||||
shift
|
||||
;;
|
||||
--) # end of options
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-*)
|
||||
echo "Error: Unsupported option $1" >&2
|
||||
usage
|
||||
;;
|
||||
*) # anything else
|
||||
echo "Error: Unsupported argument $1" >&2
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
[ -z "$address" ] && usage
|
||||
[ -z "$chain_name" ] && usage
|
||||
[ -z "$module" ] && usage
|
||||
|
||||
# Check if the git tree is dirty
|
||||
if [ "$allow_dirty" = false ]; then
|
||||
if ! git diff-index --quiet HEAD --; then
|
||||
echo "ERROR: git tree is dirty. Commit or stash your changes first." >&2
|
||||
echo "If you are sure you want to proceed, use the --force flag." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
### The script constructs the governance proposal in two different steps. First,
|
||||
### the governance prototxt (for VAA injection by the guardiand tool), then the voting/verification instructions.
|
||||
gov_msg_file=""
|
||||
|
@ -190,13 +227,17 @@ case "$chain_name" in
|
|||
explorer="https://optimistic.etherscan.io/address/"
|
||||
evm=true
|
||||
;;
|
||||
aptos)
|
||||
chain=22
|
||||
explorer="https://explorer.aptoslabs.com/account/"
|
||||
;;
|
||||
base)
|
||||
echo "Need to specify the base explorer URL!"
|
||||
exit 1
|
||||
exit 1
|
||||
chain=30
|
||||
explorer="??/address/"
|
||||
evm=true
|
||||
;;
|
||||
;;
|
||||
*)
|
||||
echo "Unknown chain: $chain_name" >&2
|
||||
exit 1
|
||||
|
@ -429,7 +470,7 @@ elif [ "$chain_name" = "solana" ] || [ "$chain_name" = "pythnet" ]; then
|
|||
|
||||
## Verify
|
||||
Contract at [$explorer$address]($explorer$address)
|
||||
|
||||
|
||||
$extra
|
||||
|
||||
Next, use the \`verify\` script to verify that the deployed bytecodes we are upgrading to match the build artifacts:
|
||||
|
@ -486,13 +527,31 @@ elif [ "$chain_name" = "terra" ]; then
|
|||
wormhole/terra$ ./verify -n mainnet -c $chain_name -w $(terra_artifact) -i $terra_code_id
|
||||
\`\`\`
|
||||
EOF
|
||||
elif [ "$chain_name" = "aptos" ]; then
|
||||
cat <<-EOF >> "$instructions_file"
|
||||
## Build
|
||||
\`\`\`shell
|
||||
wormhole/aptos $ docker build -f Dockerfile --target aptos -t aptos-build .
|
||||
\`\`\`
|
||||
|
||||
This command will build a docker image that can compile the contracts reproducibly.
|
||||
|
||||
## Verify
|
||||
Next, run the following command to check that the contract hash matches the expected value ($address):
|
||||
|
||||
\`\`\`shell
|
||||
# $module
|
||||
wormhole/aptos$ docker run -it aptos-build
|
||||
wormhole/aptos$ worm aptos hash-contracts /tmp/$module --named-addresses wormhole=0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625,deployer=0x0108bc32f7de18a5f6e1e7d6ee7aff9f5fc858d0d87ac0da94dd8d2a5d267d6b,token_bridge=0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f,nft_bridge=0x1bdffae984043833ed7fe223f7af7a3f8902d04129b14f801823e64827da7130
|
||||
wormhole/aptos$ exit
|
||||
\`\`\`
|
||||
EOF
|
||||
else
|
||||
echo "ERROR: no verification instructions for chain $chain_name" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
|
||||
cat <<-EOF >> "$instructions_file"
|
||||
## Create governance
|
||||
\`\`\`shell
|
||||
|
|
|
@ -396,7 +396,8 @@ const TESTNET = {
|
|||
core: "0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625",
|
||||
token_bridge:
|
||||
"0x576410486a2da45eee6c949c995670112ddf2fbeedab20350d506328eefc9d4f",
|
||||
nft_bridge: undefined,
|
||||
nft_bridge:
|
||||
"0x1bdffae984043833ed7fe223f7af7a3f8902d04129b14f801823e64827da7130",
|
||||
},
|
||||
sui: {
|
||||
core: "0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790",
|
||||
|
|
Loading…
Reference in New Issue