Skip to content

Commit cee5da9

Browse files
authored
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
1 parent 7cf7420 commit cee5da9

File tree

14 files changed

+295
-187
lines changed

14 files changed

+295
-187
lines changed

contract_manager/src/chains.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { KeyValueConfig, PrivateKey, Storable } from "./base";
1+
import { KeyValueConfig, PrivateKey, Storable, TxResult } from "./base";
22
import {
33
ChainName,
44
SetFee,
@@ -12,7 +12,7 @@ import {
1212
DataSource,
1313
EvmSetWormholeAddress,
1414
} from "xc_admin_common";
15-
import { AptosClient, AptosAccount, CoinClient } from "aptos";
15+
import { AptosClient, AptosAccount, CoinClient, TxnBuilderTypes } from "aptos";
1616
import Web3 from "web3";
1717
import {
1818
CosmwasmExecutor,
@@ -55,6 +55,10 @@ export abstract class Chain extends Storable {
5555
);
5656
}
5757

58+
public getWormholeChainId(): number {
59+
return toChainId(this.wormholeChainName);
60+
}
61+
5862
getId(): string {
5963
return this.id;
6064
}
@@ -509,4 +513,22 @@ export class AptosChain extends Chain {
509513
const coinClient = new CoinClient(client);
510514
return Number(await coinClient.checkBalance(account)) / 10 ** 8;
511515
}
516+
517+
async sendTransaction(
518+
senderPrivateKey: PrivateKey,
519+
txPayload: TxnBuilderTypes.TransactionPayloadEntryFunction
520+
): Promise<TxResult> {
521+
const client = this.getClient();
522+
const sender = new AptosAccount(
523+
new Uint8Array(Buffer.from(senderPrivateKey, "hex"))
524+
);
525+
const result = await client.generateSignSubmitWaitForTransaction(
526+
sender,
527+
txPayload,
528+
{
529+
maxGasAmount: BigInt(30000),
530+
}
531+
);
532+
return { id: result.hash, info: result };
533+
}
512534
}

contract_manager/src/contracts/aptos.ts

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,74 @@
11
import { Contract, PriceFeed, PrivateKey, TxResult } from "../base";
2-
import { ApiError, AptosAccount, BCS, TxnBuilderTypes } from "aptos";
2+
import { ApiError, BCS, CoinClient, TxnBuilderTypes } from "aptos";
33
import { AptosChain, Chain } from "../chains";
44
import { DataSource } from "xc_admin_common";
5-
import { CoinClient } from "aptos";
5+
import { WormholeContract } from "./wormhole";
6+
7+
type WormholeState = {
8+
chain_id: { number: string };
9+
guardian_set_index: { number: string };
10+
guardian_sets: { handle: string };
11+
};
12+
13+
type GuardianSet = {
14+
guardians: { address: { bytes: string } }[];
15+
expiration_time: { number: string };
16+
index: { number: string };
17+
};
18+
19+
export class WormholeAptosContract extends WormholeContract {
20+
constructor(public chain: AptosChain, public address: string) {
21+
super();
22+
}
23+
24+
async getState(): Promise<WormholeState> {
25+
const client = this.chain.getClient();
26+
const resources = await client.getAccountResources(this.address);
27+
const type = "WormholeState";
28+
for (const resource of resources) {
29+
if (resource.type === `${this.address}::state::${type}`) {
30+
return resource.data as WormholeState;
31+
}
32+
}
33+
throw new Error(`${type} resource not found in account ${this.address}`);
34+
}
35+
36+
async getCurrentGuardianSetIndex(): Promise<number> {
37+
const data = await this.getState();
38+
return Number(data.guardian_set_index.number);
39+
}
40+
41+
async getChainId(): Promise<number> {
42+
const data = await this.getState();
43+
return Number(data.chain_id.number);
44+
}
45+
46+
async getGuardianSet(): Promise<string[]> {
47+
const data = await this.getState();
48+
const client = this.chain.getClient();
49+
const result = (await client.getTableItem(data.guardian_sets.handle, {
50+
key_type: `u64`,
51+
value_type: `${this.address}::structs::GuardianSet`,
52+
key: data.guardian_set_index.number.toString(),
53+
})) as GuardianSet;
54+
return result.guardians.map((guardian) => guardian.address.bytes);
55+
}
56+
57+
async upgradeGuardianSets(
58+
senderPrivateKey: PrivateKey,
59+
vaa: Buffer
60+
): Promise<TxResult> {
61+
const txPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
62+
TxnBuilderTypes.EntryFunction.natural(
63+
`${this.address}::guardian_set_upgrade`,
64+
"submit_vaa_entry",
65+
[],
66+
[BCS.bcsSerializeBytes(vaa)]
67+
)
68+
);
69+
return this.chain.sendTransaction(senderPrivateKey, txPayload);
70+
}
71+
}
672

773
export class AptosContract extends Contract {
874
static type = "AptosContract";
@@ -45,25 +111,11 @@ export class AptosContract extends Contract {
45111
[BCS.bcsSerializeBytes(vaa)]
46112
)
47113
);
48-
return this.sendTransaction(senderPrivateKey, txPayload);
114+
return this.chain.sendTransaction(senderPrivateKey, txPayload);
49115
}
50116

51-
private async sendTransaction(
52-
senderPrivateKey: PrivateKey,
53-
txPayload: TxnBuilderTypes.TransactionPayloadEntryFunction
54-
): Promise<TxResult> {
55-
const client = this.chain.getClient();
56-
const sender = new AptosAccount(
57-
new Uint8Array(Buffer.from(senderPrivateKey, "hex"))
58-
);
59-
const result = await client.generateSignSubmitWaitForTransaction(
60-
sender,
61-
txPayload,
62-
{
63-
maxGasAmount: BigInt(30000),
64-
}
65-
);
66-
return { id: result.hash, info: result };
117+
public getWormholeContract(): WormholeAptosContract {
118+
return new WormholeAptosContract(this.chain, this.wormholeStateId);
67119
}
68120

69121
async executeUpdatePriceFeed(
@@ -78,7 +130,7 @@ export class AptosContract extends Contract {
78130
[BCS.serializeVectorWithFunc(vaas, "serializeBytes")]
79131
)
80132
);
81-
return this.sendTransaction(senderPrivateKey, txPayload);
133+
return this.chain.sendTransaction(senderPrivateKey, txPayload);
82134
}
83135

84136
getStateResources() {

contract_manager/src/contracts/cosmwasm.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ export class WormholeCosmWasmContract extends WormholeContract {
5454
return JSON.parse(config["\x00\x06config"])["guardian_set_index"];
5555
}
5656

57+
async getChainId(): Promise<number> {
58+
const config = await this.getConfig();
59+
return JSON.parse(config["\x00\x06config"])["chain_id"];
60+
}
61+
5762
async getGuardianSet(): Promise<string[]> {
5863
const config = await this.getConfig();
5964
const guardianSetIndex = JSON.parse(config["\x00\x06config"])[

contract_manager/src/contracts/evm.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,19 @@ const WORMHOLE_ABI = [
154154
stateMutability: "view",
155155
type: "function",
156156
},
157+
{
158+
inputs: [],
159+
name: "chainId",
160+
outputs: [
161+
{
162+
internalType: "uint16",
163+
name: "",
164+
type: "uint16",
165+
},
166+
],
167+
stateMutability: "view",
168+
type: "function",
169+
},
157170
{
158171
inputs: [
159172
{
@@ -228,6 +241,11 @@ export class WormholeEvmContract extends WormholeContract {
228241
);
229242
}
230243

244+
async getChainId(): Promise<number> {
245+
const wormholeContract = this.getContract();
246+
return Number(await wormholeContract.methods.chainId().call());
247+
}
248+
231249
/**
232250
* Returns an array of guardian addresses used for VAA verification in this contract
233251
*/

contract_manager/src/contracts/wormhole.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ import { PrivateKey, TxResult } from "../base";
33
export abstract class WormholeContract {
44
abstract getCurrentGuardianSetIndex(): Promise<number>;
55

6+
/**
7+
* Returns the chain id set in this contract.
8+
* This should match to the chain ids stored in this repo in the chains.ts file based on the network
9+
*/
10+
abstract getChainId(): Promise<number>;
11+
612
/**
713
* Returns an array of guardian addresses used for VAA verification in this contract
814
*/
@@ -31,7 +37,11 @@ export abstract class WormholeContract {
3137
const currentIndex = await this.getCurrentGuardianSetIndex();
3238
for (let i = currentIndex; i < MAINNET_UPGRADE_VAAS.length; i++) {
3339
const vaa = MAINNET_UPGRADE_VAAS[i];
34-
await this.upgradeGuardianSets(senderPrivateKey, Buffer.from(vaa, "hex"));
40+
const result = await this.upgradeGuardianSets(
41+
senderPrivateKey,
42+
Buffer.from(vaa, "hex")
43+
);
44+
console.log(`Submitted upgrade VAA ${i} with tx id ${result.id}`);
3545
// make sure the upgrade is complete before continuing
3646
while ((await this.getCurrentGuardianSetIndex()) <= i) {
3747
await new Promise((resolve) => setTimeout(resolve, 5000));

contract_manager/src/shell.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ repl.evalCode(
1010
"import { SuiContract } from './src/contracts/sui';" +
1111
"import { WormholeCosmWasmContract, CosmWasmContract } from './src/contracts/cosmwasm';" +
1212
"import { WormholeEvmContract, EvmContract } from './src/contracts/evm';" +
13-
"import { AptosContract } from './src/contracts/aptos';" +
13+
"import { WormholeAptosContract, AptosContract } from './src/contracts/aptos';" +
1414
"import { DefaultStore } from './src/store';" +
1515
"import { toPrivateKey } from './src/base';" +
1616
"DefaultStore"

contract_manager/store/chains/AptosChains.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,8 @@
88
mainnet: true
99
rpcUrl: https://fullnode.mainnet.aptoslabs.com/v1
1010
type: AptosChain
11+
- id: movement_move_devnet
12+
wormholeChainName: movement_move_devnet
13+
mainnet: false
14+
rpcUrl: https://devnet.m1.movementlabs.xyz/v1
15+
type: AptosChain

contract_manager/store/chains/EvmChains.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,3 +388,8 @@
388388
rpcUrl: https://sepolia.base.org
389389
networkId: 84532
390390
type: EvmChain
391+
- id: movement_evm_devnet
392+
mainnet: false
393+
rpcUrl: https://mevm.devnet.m1.movementlabs.xyz/v1
394+
networkId: 336
395+
type: EvmChain

contract_manager/store/contracts/AptosContracts.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,7 @@
66
stateId: "0x7e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b387"
77
wormholeStateId: "0x5bc11445584a763c1fa7ed39081f1b920954da14e04b32440cba863d03e19625"
88
type: AptosContract
9+
- chain: movement_move_devnet
10+
stateId: "0x9357e76fe965c9956a76181ee49f66d51b7f9c3800182a944ed96be86301e49f"
11+
wormholeStateId: "0x9236893d6444b208b7e0b3e8d4be4ace90b6d17817ab7d1584e46a33ef5c50c9"
12+
type: AptosContract

contract_manager/store/contracts/EvmContracts.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,3 +232,6 @@
232232
- chain: base_sepolia
233233
address: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729"
234234
type: EvmContract
235+
- chain: movement_evm_devnet
236+
address: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729"
237+
type: EvmContract

0 commit comments

Comments
 (0)