Movement move (#1211)
* [contract manager] Implement WormholeAptosContract and integrate aptos cli with the manager * Add getChainId for wormhole contracts * Add movement contracts * Simplify aptos cli
This commit is contained in:
parent
7cf7420203
commit
cee5da93d8
|
@ -1,4 +1,4 @@
|
|||
import { KeyValueConfig, PrivateKey, Storable } from "./base";
|
||||
import { KeyValueConfig, PrivateKey, Storable, TxResult } from "./base";
|
||||
import {
|
||||
ChainName,
|
||||
SetFee,
|
||||
|
@ -12,7 +12,7 @@ import {
|
|||
DataSource,
|
||||
EvmSetWormholeAddress,
|
||||
} from "xc_admin_common";
|
||||
import { AptosClient, AptosAccount, CoinClient } from "aptos";
|
||||
import { AptosClient, AptosAccount, CoinClient, TxnBuilderTypes } from "aptos";
|
||||
import Web3 from "web3";
|
||||
import {
|
||||
CosmwasmExecutor,
|
||||
|
@ -55,6 +55,10 @@ export abstract class Chain extends Storable {
|
|||
);
|
||||
}
|
||||
|
||||
public getWormholeChainId(): number {
|
||||
return toChainId(this.wormholeChainName);
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
return this.id;
|
||||
}
|
||||
|
@ -509,4 +513,22 @@ export class AptosChain extends Chain {
|
|||
const coinClient = new CoinClient(client);
|
||||
return Number(await coinClient.checkBalance(account)) / 10 ** 8;
|
||||
}
|
||||
|
||||
async sendTransaction(
|
||||
senderPrivateKey: PrivateKey,
|
||||
txPayload: TxnBuilderTypes.TransactionPayloadEntryFunction
|
||||
): Promise<TxResult> {
|
||||
const client = this.getClient();
|
||||
const sender = new AptosAccount(
|
||||
new Uint8Array(Buffer.from(senderPrivateKey, "hex"))
|
||||
);
|
||||
const result = await client.generateSignSubmitWaitForTransaction(
|
||||
sender,
|
||||
txPayload,
|
||||
{
|
||||
maxGasAmount: BigInt(30000),
|
||||
}
|
||||
);
|
||||
return { id: result.hash, info: result };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,74 @@
|
|||
import { Contract, PriceFeed, PrivateKey, TxResult } from "../base";
|
||||
import { ApiError, AptosAccount, BCS, TxnBuilderTypes } from "aptos";
|
||||
import { ApiError, BCS, CoinClient, TxnBuilderTypes } from "aptos";
|
||||
import { AptosChain, Chain } from "../chains";
|
||||
import { DataSource } from "xc_admin_common";
|
||||
import { CoinClient } from "aptos";
|
||||
import { WormholeContract } from "./wormhole";
|
||||
|
||||
type WormholeState = {
|
||||
chain_id: { number: string };
|
||||
guardian_set_index: { number: string };
|
||||
guardian_sets: { handle: string };
|
||||
};
|
||||
|
||||
type GuardianSet = {
|
||||
guardians: { address: { bytes: string } }[];
|
||||
expiration_time: { number: string };
|
||||
index: { number: string };
|
||||
};
|
||||
|
||||
export class WormholeAptosContract extends WormholeContract {
|
||||
constructor(public chain: AptosChain, public address: string) {
|
||||
super();
|
||||
}
|
||||
|
||||
async getState(): Promise<WormholeState> {
|
||||
const client = this.chain.getClient();
|
||||
const resources = await client.getAccountResources(this.address);
|
||||
const type = "WormholeState";
|
||||
for (const resource of resources) {
|
||||
if (resource.type === `${this.address}::state::${type}`) {
|
||||
return resource.data as WormholeState;
|
||||
}
|
||||
}
|
||||
throw new Error(`${type} resource not found in account ${this.address}`);
|
||||
}
|
||||
|
||||
async getCurrentGuardianSetIndex(): Promise<number> {
|
||||
const data = await this.getState();
|
||||
return Number(data.guardian_set_index.number);
|
||||
}
|
||||
|
||||
async getChainId(): Promise<number> {
|
||||
const data = await this.getState();
|
||||
return Number(data.chain_id.number);
|
||||
}
|
||||
|
||||
async getGuardianSet(): Promise<string[]> {
|
||||
const data = await this.getState();
|
||||
const client = this.chain.getClient();
|
||||
const result = (await client.getTableItem(data.guardian_sets.handle, {
|
||||
key_type: `u64`,
|
||||
value_type: `${this.address}::structs::GuardianSet`,
|
||||
key: data.guardian_set_index.number.toString(),
|
||||
})) as GuardianSet;
|
||||
return result.guardians.map((guardian) => guardian.address.bytes);
|
||||
}
|
||||
|
||||
async upgradeGuardianSets(
|
||||
senderPrivateKey: PrivateKey,
|
||||
vaa: Buffer
|
||||
): Promise<TxResult> {
|
||||
const txPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
|
||||
TxnBuilderTypes.EntryFunction.natural(
|
||||
`${this.address}::guardian_set_upgrade`,
|
||||
"submit_vaa_entry",
|
||||
[],
|
||||
[BCS.bcsSerializeBytes(vaa)]
|
||||
)
|
||||
);
|
||||
return this.chain.sendTransaction(senderPrivateKey, txPayload);
|
||||
}
|
||||
}
|
||||
|
||||
export class AptosContract extends Contract {
|
||||
static type = "AptosContract";
|
||||
|
@ -45,25 +111,11 @@ export class AptosContract extends Contract {
|
|||
[BCS.bcsSerializeBytes(vaa)]
|
||||
)
|
||||
);
|
||||
return this.sendTransaction(senderPrivateKey, txPayload);
|
||||
return this.chain.sendTransaction(senderPrivateKey, txPayload);
|
||||
}
|
||||
|
||||
private async sendTransaction(
|
||||
senderPrivateKey: PrivateKey,
|
||||
txPayload: TxnBuilderTypes.TransactionPayloadEntryFunction
|
||||
): Promise<TxResult> {
|
||||
const client = this.chain.getClient();
|
||||
const sender = new AptosAccount(
|
||||
new Uint8Array(Buffer.from(senderPrivateKey, "hex"))
|
||||
);
|
||||
const result = await client.generateSignSubmitWaitForTransaction(
|
||||
sender,
|
||||
txPayload,
|
||||
{
|
||||
maxGasAmount: BigInt(30000),
|
||||
}
|
||||
);
|
||||
return { id: result.hash, info: result };
|
||||
public getWormholeContract(): WormholeAptosContract {
|
||||
return new WormholeAptosContract(this.chain, this.wormholeStateId);
|
||||
}
|
||||
|
||||
async executeUpdatePriceFeed(
|
||||
|
@ -78,7 +130,7 @@ export class AptosContract extends Contract {
|
|||
[BCS.serializeVectorWithFunc(vaas, "serializeBytes")]
|
||||
)
|
||||
);
|
||||
return this.sendTransaction(senderPrivateKey, txPayload);
|
||||
return this.chain.sendTransaction(senderPrivateKey, txPayload);
|
||||
}
|
||||
|
||||
getStateResources() {
|
||||
|
|
|
@ -54,6 +54,11 @@ export class WormholeCosmWasmContract extends WormholeContract {
|
|||
return JSON.parse(config["\x00\x06config"])["guardian_set_index"];
|
||||
}
|
||||
|
||||
async getChainId(): Promise<number> {
|
||||
const config = await this.getConfig();
|
||||
return JSON.parse(config["\x00\x06config"])["chain_id"];
|
||||
}
|
||||
|
||||
async getGuardianSet(): Promise<string[]> {
|
||||
const config = await this.getConfig();
|
||||
const guardianSetIndex = JSON.parse(config["\x00\x06config"])[
|
||||
|
|
|
@ -154,6 +154,19 @@ const WORMHOLE_ABI = [
|
|||
stateMutability: "view",
|
||||
type: "function",
|
||||
},
|
||||
{
|
||||
inputs: [],
|
||||
name: "chainId",
|
||||
outputs: [
|
||||
{
|
||||
internalType: "uint16",
|
||||
name: "",
|
||||
type: "uint16",
|
||||
},
|
||||
],
|
||||
stateMutability: "view",
|
||||
type: "function",
|
||||
},
|
||||
{
|
||||
inputs: [
|
||||
{
|
||||
|
@ -228,6 +241,11 @@ export class WormholeEvmContract extends WormholeContract {
|
|||
);
|
||||
}
|
||||
|
||||
async getChainId(): Promise<number> {
|
||||
const wormholeContract = this.getContract();
|
||||
return Number(await wormholeContract.methods.chainId().call());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of guardian addresses used for VAA verification in this contract
|
||||
*/
|
||||
|
|
|
@ -3,6 +3,12 @@ import { PrivateKey, TxResult } from "../base";
|
|||
export abstract class WormholeContract {
|
||||
abstract getCurrentGuardianSetIndex(): Promise<number>;
|
||||
|
||||
/**
|
||||
* Returns the chain id set in this contract.
|
||||
* This should match to the chain ids stored in this repo in the chains.ts file based on the network
|
||||
*/
|
||||
abstract getChainId(): Promise<number>;
|
||||
|
||||
/**
|
||||
* Returns an array of guardian addresses used for VAA verification in this contract
|
||||
*/
|
||||
|
@ -31,7 +37,11 @@ export abstract class WormholeContract {
|
|||
const currentIndex = await this.getCurrentGuardianSetIndex();
|
||||
for (let i = currentIndex; i < MAINNET_UPGRADE_VAAS.length; i++) {
|
||||
const vaa = MAINNET_UPGRADE_VAAS[i];
|
||||
await this.upgradeGuardianSets(senderPrivateKey, Buffer.from(vaa, "hex"));
|
||||
const result = await this.upgradeGuardianSets(
|
||||
senderPrivateKey,
|
||||
Buffer.from(vaa, "hex")
|
||||
);
|
||||
console.log(`Submitted upgrade VAA ${i} with tx id ${result.id}`);
|
||||
// make sure the upgrade is complete before continuing
|
||||
while ((await this.getCurrentGuardianSetIndex()) <= i) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 5000));
|
||||
|
|
|
@ -10,7 +10,7 @@ repl.evalCode(
|
|||
"import { SuiContract } from './src/contracts/sui';" +
|
||||
"import { WormholeCosmWasmContract, CosmWasmContract } from './src/contracts/cosmwasm';" +
|
||||
"import { WormholeEvmContract, EvmContract } from './src/contracts/evm';" +
|
||||
"import { AptosContract } from './src/contracts/aptos';" +
|
||||
"import { WormholeAptosContract, AptosContract } from './src/contracts/aptos';" +
|
||||
"import { DefaultStore } from './src/store';" +
|
||||
"import { toPrivateKey } from './src/base';" +
|
||||
"DefaultStore"
|
||||
|
|
|
@ -8,3 +8,8 @@
|
|||
mainnet: true
|
||||
rpcUrl: https://fullnode.mainnet.aptoslabs.com/v1
|
||||
type: AptosChain
|
||||
- id: movement_move_devnet
|
||||
wormholeChainName: movement_move_devnet
|
||||
mainnet: false
|
||||
rpcUrl: https://devnet.m1.movementlabs.xyz/v1
|
||||
type: AptosChain
|
||||
|
|
|
@ -388,3 +388,8 @@
|
|||
rpcUrl: https://sepolia.base.org
|
||||
networkId: 84532
|
||||
type: EvmChain
|
||||
- id: movement_evm_devnet
|
||||
mainnet: false
|
||||
rpcUrl: https://mevm.devnet.m1.movementlabs.xyz/v1
|
||||
networkId: 336
|
||||
type: EvmChain
|
||||
|
|
|
@ -6,3 +6,7 @@
|
|||
stateId: "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387"
|
||||
wormholeStateId: "0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625"
|
||||
type: AptosContract
|
||||
- chain: movement_move_devnet
|
||||
stateId: "0x9357e76fe965c9956a76181ee49f66d51b7f9c3800182a944ed96be86301e49f"
|
||||
wormholeStateId: "0x9236893d6444b208b7e0b3e8d4be4ace90b6d17817ab7d1584e46a33ef5c50c9"
|
||||
type: AptosContract
|
||||
|
|
|
@ -232,3 +232,6 @@
|
|||
- chain: base_sepolia
|
||||
address: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729"
|
||||
type: EvmContract
|
||||
- chain: movement_evm_devnet
|
||||
address: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729"
|
||||
type: EvmContract
|
||||
|
|
|
@ -109,6 +109,8 @@ export const RECEIVER_CHAINS = {
|
|||
bttc_testnet: 50041,
|
||||
zksync_sepolia: 50042,
|
||||
base_sepolia: 50043,
|
||||
movement_evm_devnet: 50044,
|
||||
movement_move_devnet: 50045,
|
||||
};
|
||||
|
||||
// If there is any overlapping value the receiver chain will replace the wormhole
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
Install aptos cli with the same version specified in the ci workflows.
|
||||
|
||||
All the commands which submit transactions require an environment variable for the private key to be set.
|
||||
Depending on the network, this can be either `APTOS_LOCALNET_KEY`, `APTOS_TESTNET_KEY` or `APTOS_MAINNET_KEY`.
|
||||
All the commands which submit transactions require an environment variable `APTOS_PRIVATE_KEY` for the private key to be set.
|
||||
|
||||
# Deploying from scratch
|
||||
|
||||
|
@ -13,7 +12,10 @@ capability. You can read more about it [here](https://github.com/wormhole-founda
|
|||
Assuming the wormhole and deployer contracts are already deployed, we can deploy the pyth oracle with the following command:
|
||||
|
||||
```bash
|
||||
npm run cli deploy-pyth -- ../contracts <seed> -n testnet
|
||||
npm run cli deploy-pyth -- ../contracts <seed> \
|
||||
-n aptos_testnet \
|
||||
--deployer <deployer-address> \
|
||||
--wormhole <wormhole-address>
|
||||
```
|
||||
|
||||
`seed` can be any random string that is used for determining a specific contract address based on the seed value and the signer address.
|
||||
|
@ -30,40 +32,15 @@ wormhole = "_"
|
|||
|
||||
### Initializing pyth
|
||||
|
||||
You can run the following to initialize the pyth contract, the following is a sample (testnet) config:
|
||||
You can run the following to initialize the pyth contract:
|
||||
|
||||
```bash
|
||||
npm run cli init-pyth -- <seed> -n testnet \
|
||||
npm run cli init-pyth -- <seed> -n <network> \
|
||||
--stale-price-threshold 60 \
|
||||
--update-fee 1 \
|
||||
--governance-emitter-chain-id 1 \
|
||||
--governance-emitter-address 63278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c385 \
|
||||
--data-source-chain-ids 1 \
|
||||
--data-source-chain-ids 26 \
|
||||
--data-source-chain-ids 26 \
|
||||
--data-source-emitter-addresses f346195ac02f37d60d4db8ffa6ef74cb1be3550047543a4a9ee9acf4d78697b0 \
|
||||
--data-source-emitter-addresses a27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b6 \
|
||||
--data-source-emitter-addresses e101faedac5851e32b9b23b5f9411a8c2bac4aae3ed4dd7b811dd1a72ea4aa71
|
||||
--channel <stable-or-beta>
|
||||
```
|
||||
|
||||
The following is a sample mainnet config:
|
||||
|
||||
```bash
|
||||
npm run cli init-pyth -- <seed> -n mainnet \
|
||||
--stale-price-threshold 60 \
|
||||
--update-fee 1 \
|
||||
--governance-emitter-chain-id 1 \
|
||||
--governance-emitter-address 5635979a221c34931e32620b9293a463065555ea71fe97cd6237ade875b12e9e \
|
||||
--data-source-chain-ids 1 \
|
||||
--data-source-chain-ids 26 \
|
||||
--data-source-chain-ids 26 \
|
||||
--data-source-emitter-addresses 6bb14509a612f01fbbc4cffeebd4bbfb492a86df717ebe92eb6df432a3f00a25 \
|
||||
--data-source-emitter-addresses f8cd23c2ab91237730770bbea08d61005cdda0984348f3f6eecb559638c0bba0 \
|
||||
--data-source-emitter-addresses e101faedac5851e32b9b23b5f9411a8c2bac4aae3ed4dd7b811dd1a72ea4aa71
|
||||
```
|
||||
|
||||
Note that the `data-source-chain-ids` are paired with `data-source-emitter-addresses` and their order matters.
|
||||
|
||||
# Upgrade process:
|
||||
|
||||
The following steps are needed to upgrade our aptos contracts:
|
||||
|
|
|
@ -4,34 +4,40 @@ import { AptosAccount, AptosClient, BCS, TxnBuilderTypes } from "aptos";
|
|||
import fs from "fs";
|
||||
import sha3 from "js-sha3";
|
||||
import { ethers } from "ethers";
|
||||
import {
|
||||
AptosChain,
|
||||
DefaultStore,
|
||||
getDefaultDeploymentConfig,
|
||||
} from "contract_manager";
|
||||
|
||||
const LOCALNET: string = "localnet";
|
||||
const TESTNET: string = "testnet";
|
||||
const MAINNET: string = "mainnet";
|
||||
|
||||
interface Network {
|
||||
// RPC endpoint of the network
|
||||
endpoint: string;
|
||||
// Private key of the network
|
||||
key: string | undefined;
|
||||
}
|
||||
const NETWORK_CHOICES = Object.entries(DefaultStore.chains)
|
||||
.filter(([chain, config]) => {
|
||||
return config instanceof AptosChain;
|
||||
})
|
||||
.map(([chain, _]) => {
|
||||
return chain;
|
||||
});
|
||||
|
||||
const NETWORK_OPTION = {
|
||||
alias: "n",
|
||||
describe: "network",
|
||||
type: "string",
|
||||
choices: [LOCALNET, TESTNET, MAINNET],
|
||||
choices: NETWORK_CHOICES,
|
||||
demandOption: true,
|
||||
} as const;
|
||||
const CHANNEL_OPTION = {
|
||||
describe: "channel",
|
||||
type: "string",
|
||||
choices: ["stable", "beta"],
|
||||
demandOption: true,
|
||||
} as const;
|
||||
const DEPLOYER_OPTION = {
|
||||
describe: "deployer contract address deployed in the network",
|
||||
type: "string",
|
||||
default: "0xb31e712b26fd295357355f6845e77c888298636609e93bc9b05f0f604049f434",
|
||||
} as const;
|
||||
const WORMHOLE_OPTION = {
|
||||
describe: "wormhole contract address deployed in the network",
|
||||
type: "string",
|
||||
default: "0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625",
|
||||
} as const;
|
||||
const PYTH_OPTION = {
|
||||
describe: "pyth contract address deployed in the network",
|
||||
|
@ -50,29 +56,6 @@ interface PackageBCS {
|
|||
codeHash: Uint8Array;
|
||||
}
|
||||
|
||||
const networks = new Map<string, Network>([
|
||||
[
|
||||
LOCALNET,
|
||||
{
|
||||
key: process.env["APTOS_LOCALNET_KEY"],
|
||||
endpoint: "http://0.0.0.0:8080",
|
||||
},
|
||||
],
|
||||
[
|
||||
TESTNET,
|
||||
{
|
||||
key: process.env["APTOS_TESTNET_KEY"],
|
||||
endpoint: "https://fullnode.testnet.aptoslabs.com/v1",
|
||||
},
|
||||
],
|
||||
[
|
||||
MAINNET,
|
||||
{
|
||||
key: process.env["APTOS_MAINNET_KEY"],
|
||||
endpoint: "https://fullnode.mainnet.aptoslabs.com/v1",
|
||||
},
|
||||
],
|
||||
]);
|
||||
export const builder: (args: Argv<any>) => Argv<any> = (yargs) =>
|
||||
yargs
|
||||
.command(
|
||||
|
@ -101,6 +84,37 @@ export const builder: (args: Argv<any>) => Argv<any> = (yargs) =>
|
|||
await executeTransaction(argv.network, txPayload);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
"deploy-wormhole <package-dir> <seed>",
|
||||
"Deploy the wormhole package using a resource account.",
|
||||
(yargs) => {
|
||||
return yargs
|
||||
.positional("package-dir", { type: "string" })
|
||||
.positional("seed", { type: "string" })
|
||||
.option("deployer", DEPLOYER_OPTION)
|
||||
.option("network", NETWORK_OPTION);
|
||||
},
|
||||
async (argv) => {
|
||||
const sender = getSender();
|
||||
const derivedAddress = generateDerivedAddress(
|
||||
sender.address().toString(),
|
||||
argv.seed!
|
||||
);
|
||||
|
||||
const namedAddresses = `deployer=${argv.deployer},wormhole=0x${derivedAddress}`;
|
||||
console.log("Building the package with the following named addresses:");
|
||||
console.log(`Deployer=${argv.deployer}`);
|
||||
console.log(`Wormhole=${derivedAddress}`);
|
||||
const txPayload = createDeployDerivedTransaction(
|
||||
argv["package-dir"],
|
||||
argv.deployer,
|
||||
argv.seed,
|
||||
namedAddresses
|
||||
);
|
||||
|
||||
await executeTransaction(argv.network, txPayload);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
"deploy-pyth <package-dir> <seed>",
|
||||
"Deploy the pyth package using a resource account.",
|
||||
|
@ -113,7 +127,7 @@ export const builder: (args: Argv<any>) => Argv<any> = (yargs) =>
|
|||
.option("network", NETWORK_OPTION);
|
||||
},
|
||||
async (argv) => {
|
||||
const sender = getSender(argv.network);
|
||||
const sender = getSender();
|
||||
const derivedAddress = generateDerivedAddress(
|
||||
sender.address().toString(),
|
||||
argv.seed!
|
||||
|
@ -124,36 +138,31 @@ export const builder: (args: Argv<any>) => Argv<any> = (yargs) =>
|
|||
console.log(`Wormhole=${argv.wormhole}`);
|
||||
console.log(`Deployer=${argv.deployer}`);
|
||||
console.log(`Pyth=${derivedAddress}`);
|
||||
const artifact = serializePackage(
|
||||
buildPackage(argv["package-dir"]!, namedAddresses)
|
||||
);
|
||||
|
||||
const txPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
|
||||
TxnBuilderTypes.EntryFunction.natural(
|
||||
argv.deployer + "::deployer",
|
||||
"deploy_derived",
|
||||
[],
|
||||
[
|
||||
artifact.meta,
|
||||
artifact.bytecodes,
|
||||
BCS.bcsSerializeBytes(Buffer.from(argv["seed"]!, "ascii")),
|
||||
]
|
||||
)
|
||||
const txPayload = createDeployDerivedTransaction(
|
||||
argv["package-dir"],
|
||||
argv.deployer,
|
||||
argv.seed,
|
||||
namedAddresses
|
||||
);
|
||||
|
||||
await executeTransaction(argv.network, txPayload);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
"derived-address <seed> <signer>",
|
||||
"derived-address <seed>",
|
||||
"Generate the derived address for the given seed and sender address",
|
||||
(yargs) => {
|
||||
return yargs
|
||||
.positional("seed", { type: "string", demandOption: true })
|
||||
.positional("signer", { type: "string", demandOption: true });
|
||||
.option("signer", { type: "string" });
|
||||
},
|
||||
async (argv) => {
|
||||
console.log(generateDerivedAddress(argv.signer, argv.seed));
|
||||
console.log(
|
||||
generateDerivedAddress(
|
||||
argv.signer || getSender().address().toString(),
|
||||
argv.seed
|
||||
)
|
||||
);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
|
@ -162,39 +171,15 @@ export const builder: (args: Argv<any>) => Argv<any> = (yargs) =>
|
|||
(yargs) => {
|
||||
return yargs
|
||||
.option("network", NETWORK_OPTION)
|
||||
.option("chain-id", {
|
||||
describe: "Chain id",
|
||||
type: "number",
|
||||
default: 22,
|
||||
demandOption: false,
|
||||
})
|
||||
.option("governance-chain-id", {
|
||||
describe: "Governance chain id",
|
||||
type: "number",
|
||||
default: 1,
|
||||
demandOption: false,
|
||||
})
|
||||
.option("governance-address", {
|
||||
describe: "Governance address",
|
||||
type: "string",
|
||||
default:
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000004",
|
||||
demandOption: false,
|
||||
})
|
||||
.option("guardian-address", {
|
||||
alias: "g",
|
||||
demandOption: true,
|
||||
describe: "Initial guardian's address",
|
||||
type: "string",
|
||||
});
|
||||
.option("channel", CHANNEL_OPTION);
|
||||
},
|
||||
async (argv) => {
|
||||
const guardian_address = evm_address(
|
||||
argv["guardian-address"]
|
||||
).substring(24);
|
||||
const chain_id = argv["chain-id"];
|
||||
const governance_address = evm_address(argv["governance-address"]);
|
||||
const governance_chain_id = argv["governance-chain-id"];
|
||||
const chain_id = DefaultStore.chains[argv.network].getWormholeChainId();
|
||||
const config = getDefaultDeploymentConfig(argv.channel).wormholeConfig;
|
||||
|
||||
const governance_contract = config.governanceContract;
|
||||
const governance_chain_id = config.governanceChainId;
|
||||
const guardian_address = config.initialGuardianSet[0]; // assuming only one guardian for now
|
||||
|
||||
const guardian_addresses_serializer = new BCS.Serializer();
|
||||
guardian_addresses_serializer.serializeU32AsUleb128(1);
|
||||
|
@ -205,10 +190,10 @@ export const builder: (args: Argv<any>) => Argv<any> = (yargs) =>
|
|||
const args = [
|
||||
BCS.bcsSerializeUint64(chain_id),
|
||||
BCS.bcsSerializeUint64(governance_chain_id),
|
||||
BCS.bcsSerializeBytes(Buffer.from(governance_address, "hex")),
|
||||
BCS.bcsSerializeBytes(Buffer.from(governance_contract, "hex")),
|
||||
guardian_addresses_serializer.getBytes(),
|
||||
];
|
||||
const sender = getSender(argv.network);
|
||||
const sender = getSender();
|
||||
const wormholeAddress = generateDerivedAddress(
|
||||
sender.address().hex(),
|
||||
"wormhole"
|
||||
|
@ -216,7 +201,7 @@ export const builder: (args: Argv<any>) => Argv<any> = (yargs) =>
|
|||
const txPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
|
||||
TxnBuilderTypes.EntryFunction.natural(
|
||||
`${wormholeAddress}::wormhole`,
|
||||
"init_2",
|
||||
"init",
|
||||
[],
|
||||
args
|
||||
)
|
||||
|
@ -237,57 +222,37 @@ export const builder: (args: Argv<any>) => Argv<any> = (yargs) =>
|
|||
type: "number",
|
||||
demandOption: true,
|
||||
})
|
||||
.option("governance-emitter-chain-id", {
|
||||
describe: "Governance emitter chain id",
|
||||
type: "number",
|
||||
demandOption: true,
|
||||
})
|
||||
.option("governance-emitter-address", {
|
||||
describe: "Governance emitter address",
|
||||
type: "string",
|
||||
demandOption: true,
|
||||
})
|
||||
.option("update-fee", {
|
||||
describe: "Update fee",
|
||||
type: "number",
|
||||
demandOption: true,
|
||||
})
|
||||
.option("data-source-chain-ids", {
|
||||
describe: "Data source chain IDs",
|
||||
type: "array",
|
||||
demandOption: true,
|
||||
})
|
||||
.option("data-source-emitter-addresses", {
|
||||
describe: "Data source emitter addresses",
|
||||
type: "array",
|
||||
demandOption: true,
|
||||
});
|
||||
.option("channel", CHANNEL_OPTION);
|
||||
},
|
||||
async (argv) => {
|
||||
const stale_price_threshold = argv["stale-price-threshold"];
|
||||
const governance_emitter_chain_id = argv["governance-emitter-chain-id"];
|
||||
const governance_emitter_address = evm_address(
|
||||
argv["governance-emitter-address"]
|
||||
);
|
||||
const update_fee = argv["update-fee"];
|
||||
|
||||
const config = getDefaultDeploymentConfig(argv.channel);
|
||||
const governance_emitter_chain_id =
|
||||
config.governanceDataSource.emitterChain;
|
||||
const governance_emitter_address =
|
||||
config.governanceDataSource.emitterAddress;
|
||||
|
||||
const dataSourceChainIdsSerializer = new BCS.Serializer();
|
||||
dataSourceChainIdsSerializer.serializeU32AsUleb128(
|
||||
argv["data-source-chain-ids"].length
|
||||
config.dataSources.length
|
||||
);
|
||||
argv["data-source-chain-ids"].forEach((chain_id: number) =>
|
||||
dataSourceChainIdsSerializer.serializeU64(chain_id)
|
||||
);
|
||||
|
||||
const dataSourceEmitterAddressesSerializer = new BCS.Serializer();
|
||||
dataSourceEmitterAddressesSerializer.serializeU32AsUleb128(
|
||||
argv["data-source-emitter-addresses"].length
|
||||
config.dataSources.length
|
||||
);
|
||||
argv["data-source-emitter-addresses"].forEach((emitter_address) => {
|
||||
config.dataSources.forEach((ds) => {
|
||||
dataSourceChainIdsSerializer.serializeU64(ds.emitterChain);
|
||||
dataSourceEmitterAddressesSerializer.serializeBytes(
|
||||
Buffer.from(emitter_address as string, "hex")
|
||||
Buffer.from(ds.emitterAddress, "hex")
|
||||
);
|
||||
});
|
||||
const update_fee = argv["update-fee"];
|
||||
|
||||
const args = [
|
||||
BCS.bcsSerializeUint64(stale_price_threshold),
|
||||
|
@ -297,7 +262,7 @@ export const builder: (args: Argv<any>) => Argv<any> = (yargs) =>
|
|||
dataSourceEmitterAddressesSerializer.getBytes(),
|
||||
BCS.bcsSerializeUint64(update_fee),
|
||||
];
|
||||
const sender = getSender(argv.network);
|
||||
const sender = getSender();
|
||||
const pythAddress = generateDerivedAddress(
|
||||
sender.address().hex(),
|
||||
argv.seed
|
||||
|
@ -383,7 +348,8 @@ export const builder: (args: Argv<any>) => Argv<any> = (yargs) =>
|
|||
.option("network", NETWORK_OPTION);
|
||||
},
|
||||
async (argv) => {
|
||||
const endpoint = networks.get(argv.network)!.endpoint;
|
||||
const endpoint = (DefaultStore.chains[argv.network] as AptosChain)
|
||||
.rpcUrl;
|
||||
const addr1 = argv["addr-1"];
|
||||
const addr2 = argv["addr-2"];
|
||||
const url = `${endpoint}/accounts/${addr1}/resource/0x1::code::PackageRegistry`;
|
||||
|
@ -416,22 +382,23 @@ export const builder: (args: Argv<any>) => Argv<any> = (yargs) =>
|
|||
)
|
||||
.demandCommand();
|
||||
|
||||
function getSender(network: string) {
|
||||
if (networks.get(network)!.key === undefined) {
|
||||
function getSender() {
|
||||
const key = process.env["APTOS_PRIVATE_KEY"];
|
||||
if (key === undefined) {
|
||||
throw new Error(
|
||||
`No key for network ${network}. Please set the APTOS_${network.toUpperCase()}_KEY environment variable.`
|
||||
`Please set the APTOS_PRIVATE_KEY environment variable to the private key of the sender in hex format`
|
||||
);
|
||||
}
|
||||
return new AptosAccount(
|
||||
new Uint8Array(Buffer.from(networks.get(network)!.key!, "hex"))
|
||||
);
|
||||
return new AptosAccount(new Uint8Array(Buffer.from(key, "hex")));
|
||||
}
|
||||
|
||||
async function executeTransaction(
|
||||
network: string,
|
||||
txPayload: TxnBuilderTypes.TransactionPayloadEntryFunction
|
||||
) {
|
||||
const client = new AptosClient(networks.get(network)!.endpoint);
|
||||
const sender = getSender(network);
|
||||
const endpoint = (DefaultStore.chains[network] as AptosChain).rpcUrl;
|
||||
const client = new AptosClient(endpoint);
|
||||
const sender = getSender();
|
||||
console.log(
|
||||
await client.generateSignSubmitWaitForTransaction(sender, txPayload, {
|
||||
maxGasAmount: BigInt(30000),
|
||||
|
@ -528,6 +495,28 @@ function serializePackage(p: Package): PackageBCS {
|
|||
};
|
||||
}
|
||||
|
||||
function createDeployDerivedTransaction(
|
||||
packageDir: string,
|
||||
deployer: string,
|
||||
seed: string,
|
||||
namedAddresses: string
|
||||
) {
|
||||
const artifact = serializePackage(buildPackage(packageDir, namedAddresses));
|
||||
|
||||
return new TxnBuilderTypes.TransactionPayloadEntryFunction(
|
||||
TxnBuilderTypes.EntryFunction.natural(
|
||||
deployer + "::deployer",
|
||||
"deploy_derived",
|
||||
[],
|
||||
[
|
||||
artifact.meta,
|
||||
artifact.bytecodes,
|
||||
BCS.bcsSerializeBytes(Buffer.from(seed, "ascii")),
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function hex(x: string): string {
|
||||
return ethers.utils.hexlify(x, { allowMissingPrefix: true });
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
[
|
||||
{
|
||||
"contractName": "Migrations",
|
||||
"address": "0xf5BBe9558F4Bf37F1eB82fb2CEdb1C775FA56832"
|
||||
},
|
||||
{
|
||||
"contractName": "WormholeReceiver",
|
||||
"address": "0x8250f4aF4B972684F7b336503E2D6dFeDeB1487a",
|
||||
"transactionHash": "0x9e86ade70d9383cb16171450d6047f60d9df8061a165988abd52735e66d35126"
|
||||
},
|
||||
{
|
||||
"contractName": "PythUpgradable",
|
||||
"address": "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729",
|
||||
"transactionHash": "0xc5a932f9bf50032493843be32939929f6bd9ec848ff8aa52f91489d31f403145"
|
||||
}
|
||||
]
|
Loading…
Reference in New Issue