wormhole/terra/tools/test_interface_update.ts

835 lines
35 KiB
TypeScript

// Run with MNEMONIC="" npx tsx test_interface_update.ts
// The intention of this script is to test the CW < 1 migration to CW > 1.
// 1. Instantiate new core and token bridge contracts from the existing Code IDs, using the devnet Guardian key.
// 2. Migrate those contracts to the same code IDs, triggering any migration-specific effect they may have had.
// 3. Register a foreign bridge and asset.
// 4. Send a foreign asset in and out. (actually, can't create a foreign asset so nvm)
// 5. Store the updated CW > 1 code to new code IDs.
// 6. Upgrade the contracts to the new code IDs.
// 7. Upgrade the contracts to the new code IDs again.
// 8. Send the foreign asset from step 4 in and out again.
// 9. Register another foreign bridge and asset.
// 10. Send a new foreign asset in and out. (skipping since 8 was new anyway due to being unable to complete 4)
// 11. Attest a native token.
// 12. Deposit and withdraw a native token. (This is broken in mainnet, but should be fixed with this upgrade.)
// 13. Send a native token out and back. (This is broken in mainnet, but should be fixed with this upgrade.)
// 14. Confirm that a VAA redeemed before the upgrade can't be redeemed again (like from step 3)
// 15. Send a 20-byte addressed native CW20 out and in
// 16. Send a 32-byte addressed native CW20 out and in
import "dotenv/config";
import {
Fee,
LCDClient,
MnemonicKey,
MsgUpdateContractAdmin,
} from "@terra-money/terra.js";
import {
MsgInstantiateContract,
MsgExecuteContract,
MsgStoreCode,
} from "@terra-money/terra.js";
import { readFileSync } from "fs";
import { Bech32, toHex } from "@cosmjs/encoding";
import { zeroPad } from "ethers/lib/utils.js";
// gas estimation wasn't working, so you'll find many hardcoded values in here
// YMMV
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// look, broadcast and broadcastBlock still resulted in sequence mismatches
// and nobody has time for that
async function broadcastAndWait(terra, tx) {
const response = await terra.tx.broadcast(tx);
if (response?.code !== 0) {
console.error(response);
throw new Error(
`Transaction failed https://finder.terraclassic.community/mainnet/tx/${response?.txhash}`
);
}
let currentHeight = (await terra.tendermint.blockInfo()).block.header.height;
while (currentHeight <= response.height) {
await sleep(100);
currentHeight = (await terra.tendermint.blockInfo()).block.header.height;
}
return response;
}
// Terra addresses are "human-readable", but for cross-chain registrations, we
// want the "canonical" version
function convert_terra_address_to_hex(human_addr) {
return "0x" + toHex(zeroPad(Bech32.decode(human_addr).data, 32));
}
async function submitCoreBridgeVAA(vaa: string) {
const tx = await wallet.createAndSignTx({
msgs: [
new MsgExecuteContract(wallet.key.accAddress, addressCoreBridge, {
submit_v_a_a: {
vaa: Buffer.from(vaa, "hex").toString("base64"),
},
}),
],
memo: "",
fee: new Fee(1000000, { uluna: 50_000_000 }),
});
const response = await broadcastAndWait(terra, tx);
return response?.txhash;
}
async function submitTokenBridgeVAA(vaa: string) {
const tx = await wallet.createAndSignTx({
msgs: [
new MsgExecuteContract(wallet.key.accAddress, addressTokenBridge, {
submit_vaa: {
data: Buffer.from(vaa, "hex").toString("base64"),
},
}),
],
memo: "",
fee: new Fee(1000000, { uluna: 50_000_000 }),
});
const response = await broadcastAndWait(terra, tx);
return response?.txhash;
}
/* Set up terra client & wallet */
const terra = new LCDClient({
URL: "https://terra-classic-lcd.publicnode.com",
chainID: "columbus-5",
isClassic: false,
});
if (!process.env.MNEMONIC) {
throw new Error("MNEMONIC is required");
}
const wallet = terra.wallet(
new MnemonicKey({
mnemonic: process.env.MNEMONIC,
})
);
const existingCodeIds = {
"wormhole.wasm": 557, // current wasm
"token_bridge_terra.wasm": 6097, // current wasm
"cw20_wrapped.wasm": 767, // current wasm
};
// default addresses from first run
let addressCoreBridge: string =
"terra1xd3f9g77qd5774kkepnn7wndjdlqujsvp5kg0pj7yp55crgvju7snjjgxc";
let addressTokenBridge: string =
"terra1kxp07aarhyurar4r4ertszlvhhjmt07j3fusdfu9pj4akkrdcdys9694q2";
async function deployCode(file: string) {
const contract_bytes = readFileSync(`../artifacts/${file}`);
console.log(`Storing WASM: ${file} (${contract_bytes.length} bytes)`);
const store_code = new MsgStoreCode(
wallet.key.accAddress,
contract_bytes.toString("base64")
);
const tx = await wallet.createAndSignTx({
msgs: [store_code],
memo: "",
fee: new Fee(5000000, { uluna: 200_000_000 }),
});
const rs = await broadcastAndWait(terra, tx);
console.log(rs.raw_log);
console.log(
`Deployed ${file} https://finder.terraclassic.community/mainnet/tx/${rs?.txhash}`
);
const ci = /"code_id","value":"([^"]+)/gm.exec(rs.raw_log)?.[1];
if (!ci) {
throw new Error("Could not parse code ID from raw_log");
}
return parseInt(ci);
}
async function instantiate(contract, inst_msg, label) {
var address;
await wallet
.createAndSignTx({
msgs: [
new MsgInstantiateContract(
wallet.key.accAddress,
wallet.key.accAddress,
existingCodeIds[contract],
inst_msg,
undefined,
label
),
],
memo: "",
fee: new Fee(5000000, { uluna: 200_000_000 }),
})
.then((tx) => broadcastAndWait(terra, tx))
.then((rs) => {
address = /"_contract_address","value":"([^"]+)/gm.exec(rs.raw_log)?.[1];
});
console.log(
`Instantiated ${contract} at ${address} (${convert_terra_address_to_hex(
address
)})`
);
return address;
}
async function step1() {
const govChain = 1;
const govAddress =
"0000000000000000000000000000000000000000000000000000000000000004";
// devnet guardian public key
const init_guardians = ["beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe"];
addressCoreBridge = await instantiate(
"wormhole.wasm",
{
gov_chain: govChain,
gov_address: Buffer.from(govAddress, "hex").toString("base64"),
guardian_set_expirity: 86400,
initial_guardian_set: {
addresses: init_guardians.map((hex) => {
return {
bytes: Buffer.from(hex, "hex").toString("base64"),
};
}),
expiration_time: 0,
},
},
"wormholeTest"
);
addressTokenBridge = await instantiate(
"token_bridge_terra.wasm",
{
gov_chain: govChain,
gov_address: Buffer.from(govAddress, "hex").toString("base64"),
wormhole_contract: addressCoreBridge,
wrapped_asset_code_id: existingCodeIds["cw20_wrapped.wasm"],
},
"tokenBridgeTest"
);
}
async function step2() {
async function updateAdmin(contract: string) {
const tx = await wallet.createAndSignTx({
msgs: [
new MsgUpdateContractAdmin(wallet.key.accAddress, contract, contract),
],
memo: "",
fee: new Fee(200000, { uluna: 10_000_000 }),
});
const response = await broadcastAndWait(terra, tx);
console.log(
`Updated ${contract} admin to itself https://finder.terraclassic.community/mainnet/tx/${response?.txhash}`
);
}
await updateAdmin(addressCoreBridge);
await updateAdmin(addressTokenBridge);
{
// worm generate upgrade -c terra -a 557 -m Core -g cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
const upgradeCoreVaa =
"01000000000100873cedead0c5a60da23bc23b3705e3b5b0600630d61a955c308307565e54b0cc14914495fc0eb39aee667f81adde5f49aec8bb774bb34121130e24ad6ecacb4c000000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000005300d3f0000000000000000000000000000000000000000000000000000000000436f7265010003000000000000000000000000000000000000000000000000000000000000022d";
const txhash = await submitCoreBridgeVAA(upgradeCoreVaa);
console.log(
`Upgraded core bridge https://finder.terraclassic.community/mainnet/tx/${txhash}`
);
}
{
// worm generate upgrade -c terra -a 6097 -m TokenBridge -g cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
const upgradeTokenBridgeVaa =
"01000000000100c6267b6d66e0ff7fd1b625a94402a5c3ea04cbda7157ab42e172a5844f0cdc495e327c9e1cb9acf2f6c07597d8e746f593253cdaed451994765de1b8ae6fc3d9010000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000001be411000000000000000000000000000000000000000000000546f6b656e42726964676502000300000000000000000000000000000000000000000000000000000000000017d1";
// Unable to run this... 'failed to execute message; message index: 0: Generic error: Querier contract error: codespace: wasm, code: 9: execute wasm contract failed'
// const txhash = await submitTokenBridgeVAA(upgradeCoreVaa);
// console.log(
// `Upgraded token bridge https://finder.terraclassic.community/mainnet/tx/${txhash}`
// );
}
}
const registerAvalanche =
"010000000001000f4c334aad9d3a3a9025654bdc5b6c544962683d3be6f616e2e8bdb4f0c2d292423c12b62ea1761c208fb2f3c3734dc25110d7ec7bed9d5db64f2f4babd17eaf010000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000002cb3d3900000000000000000000000000000000000000000000546f6b656e42726964676501000000060000000000000000000000000e082f06ff657d94310cb8ce8b0d9a04541d8052";
async function step3() {
{
// Avalanche mainnet token bridge registration
// worm generate registration -c avalanche -a 0e082F06FF657D94310cB8cE8B0D9a04541d8052 -m TokenBridge -g cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
const txhash = await submitTokenBridgeVAA(registerAvalanche);
console.log(
`Registered Avalanche https://finder.terraclassic.community/mainnet/tx/${txhash}`
);
}
{
// WAVAX attestation
// worm edit-vaa -v AQAAAAMNAaDxJk8ByJTD1FsV4F2ZHyoV1/ZgDvhf+CsKmVTXt5PsdmTurfZKrcr752G94X6ghbT46rxr0bPy4NkoX7MKQJwAAk/crb5HuZnwmD+C6MFIeIBySqvxDQ/mssXHthZrQFsyLvmGZ8COYM9lZEb9pCoiBxuni4pG8gfSH/hEbIkLfX8AA43O2Ymg124dnkzw1E3dIhMt0qKMJozhXdzL/09cB4aJDWX5qxColViikLBqFqM/H/TUasl6Mq2Adhxb6U0h9LEABHAKcM3HK4mPKvPO/tLHW1obzvfp1Dr9QnrkXa+Nh9NMCzHI/JjaUxqUv+9CWntOX3UkGhSkcG0OnjWT79Z1B6kBBd1hBteD0zsrftlGvKzBC9uK3tJ6qwC/YOt0G5criYsqetYTgYnXpZiNrUBdKsqloNUpYHkkE/ieDDFUYxu8IwQAB6NfbF5YrI97b8EoQpz6IW93rJyymNFjYZpFQ3g4gDnoNQpqU0x6xH9NAVq1jJa1sdXjqFnDFDIPJxVHZvX0nAkBCl+kaIABlDgB2TyYvNop2DHKdLj1/NFVqspxg2OZ+PFpcYWZnhIJpNR2YTS7fppI9chxGGoVaoF2ufGAA155kiYAC/2UFf45V9DrsDiW5oJd74PXz3GvbB7G78me4NBYTlZ6E2U9RUQ8ib2W2G7NyQAh2rA/0v9oVbFMOjHaovp4E0kADIUXrdHj7UphaDMNVmFI8uPbLTNHh1j0yweg9TorA3i9QVG++wJ8mFW/+qCMhcw4M5MkJKhbohEQSTdiENir/hkBDgmH2Mb76kLUpy72LBbuQmbzTxb/72PRSqIpMLQzaCbmMGlpUaK3vgZETvUZjjBgt4pMDzki6KjZ67bXhp8FsFoAD/VLPF3juH6/5ulXqmMKP3VJts/ZTzhvn7yRV+YA5YjXUdzUh3pYbraURIsrXvJKzp9+bLzLh2OX/8XRU3bPfLgAEBhwvU9CUEiZ5+3jwSEl3u7rF7ADfUCFeSc/Tb46brgtZNf06ps56C9GKa/c6pSIXEKFjm6AyptXkCeIA9/MdioBEZcYyMrEYkW+gUFGCAaoSSyQmdTmydElc514U3inTM9FETZNTCFmxK/5VHnbEgLKBiDCXL6VDqr8pqBe5DzPxtoAZXIwrDh5AAAABgAAAAAAAAAAAAAAAA4ILwb/ZX2UMQy4zosNmgRUHYBSAAAAAAABqd0BAgAAAAAAAAAAAAAAALMfZqo8HnhTY/CHWht04nuF/WbHAAYSV0FWQVgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABXcmFwcGVkIEFWQVgAAAAAAAAAAAAAAAAAAAAAAAAAAA== --gs cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
const wavaxAttestation =
"01000000000100b1cc54a6b6a3ee8baadc39f7f59b6074ae647d811ffb3deac1036231dfdc26f02a0e6fa6033f549efc358e7443d979bd261ab3ad8f74ce6f90c14cb136a6832701657230ac3879000000060000000000000000000000000e082f06ff657d94310cb8ce8b0d9a04541d8052000000000001a9dd0102000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c700061257415641580000000000000000000000000000000000000000000000000000005772617070656420415641580000000000000000000000000000000000000000";
// Unable to run this... 'failed to execute message; message index: 0: dispatch: submessages: label is required: invalid request'
// const txhash = await submitTokenBridgeVAA(wavaxAttestation);
// console.log(
// `Created WAVAX https://finder.terraclassic.community/mainnet/tx/${txhash}`
// );
}
}
async function step4() {
// cannot complete step 4 since unable to create the wrapped asset on the existing implementation
}
// default code id from first run
let newCodeIdCoreBridge: number = 8336;
let newCodeIdTokenBridge: number = 8337;
async function step5() {
newCodeIdCoreBridge = await deployCode("wormhole.wasm");
newCodeIdTokenBridge = await deployCode("token_bridge_terra.wasm");
}
async function step6() {
{
// worm generate upgrade -c terra -a 8333 -m Core -g cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
const upgradeCoreVaa =
"01000000000100184d8fd19d0156cbba2c04e93d9f6a13af14388866a6acadde0db5a323deb0c23e40fe42ab52c285453b76fc535a64aa0f9d97f90dc44ca1079c50b7f5a10dc0000000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000005dbae8f0000000000000000000000000000000000000000000000000000000000436f72650100030000000000000000000000000000000000000000000000000000000000002090";
const txhash = await submitCoreBridgeVAA(upgradeCoreVaa);
console.log(
`Upgraded core bridge https://finder.terraclassic.community/mainnet/tx/${txhash}`
);
}
{
// worm generate upgrade -c terra -a 8334 -m TokenBridge -g cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
const upgradeTokenBridgeVaa =
"010000000001007e4d9ebea907f55fcf011b7419812707200adc237c5159364486f95e182b98622eab205b0be2af96eb9a5010ab8b2ea3103c5ac5080a7ab9ce42a2bbfa70462f0100000001000000010001000000000000000000000000000000000000000000000000000000000000000400000000000913c800000000000000000000000000000000000000000000546f6b656e4272696467650200030000000000000000000000000000000000000000000000000000000000002091";
const txhash = await submitTokenBridgeVAA(upgradeTokenBridgeVaa);
console.log(
`Upgraded token bridge https://finder.terraclassic.community/mainnet/tx/${txhash}`
);
}
}
async function step7() {
{
// worm generate upgrade -c terra -a 8333 -m Core -g cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
const upgradeCoreVaa =
"0100000000010076c3cea65bb6a1657a5d4736133fcc9dd1c7ff363715e4d4291461e98430f3a7238f12d26bf3b7715915628ed178726d161e594d9722440e01f797658e52351b000000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000005b35c780000000000000000000000000000000000000000000000000000000000436f72650100030000000000000000000000000000000000000000000000000000000000002090";
const txhash = await submitCoreBridgeVAA(upgradeCoreVaa);
console.log(
`Upgraded core bridge https://finder.terraclassic.community/mainnet/tx/${txhash}`
);
}
{
// worm generate upgrade -c terra -a 8334 -m TokenBridge -g cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
const upgradeTokenBridgeVaa =
"01000000000100ae7e1701c5b289ecee8e75140050d5166f8683769e0b6c04f9623331f6c6bfcc068c7fb7ad723c991411bc8eca5a405a8614fe11aa4a9f9861e3a0af06a5c859010000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000005c295db00000000000000000000000000000000000000000000546f6b656e4272696467650200030000000000000000000000000000000000000000000000000000000000002091";
const txhash = await submitTokenBridgeVAA(upgradeTokenBridgeVaa);
console.log(
`Upgraded token bridge https://finder.terraclassic.community/mainnet/tx/${txhash}`
);
}
}
async function step8a() {
{
// WAVAX attestation
// worm edit-vaa -v AQAAAAMNAaDxJk8ByJTD1FsV4F2ZHyoV1/ZgDvhf+CsKmVTXt5PsdmTurfZKrcr752G94X6ghbT46rxr0bPy4NkoX7MKQJwAAk/crb5HuZnwmD+C6MFIeIBySqvxDQ/mssXHthZrQFsyLvmGZ8COYM9lZEb9pCoiBxuni4pG8gfSH/hEbIkLfX8AA43O2Ymg124dnkzw1E3dIhMt0qKMJozhXdzL/09cB4aJDWX5qxColViikLBqFqM/H/TUasl6Mq2Adhxb6U0h9LEABHAKcM3HK4mPKvPO/tLHW1obzvfp1Dr9QnrkXa+Nh9NMCzHI/JjaUxqUv+9CWntOX3UkGhSkcG0OnjWT79Z1B6kBBd1hBteD0zsrftlGvKzBC9uK3tJ6qwC/YOt0G5criYsqetYTgYnXpZiNrUBdKsqloNUpYHkkE/ieDDFUYxu8IwQAB6NfbF5YrI97b8EoQpz6IW93rJyymNFjYZpFQ3g4gDnoNQpqU0x6xH9NAVq1jJa1sdXjqFnDFDIPJxVHZvX0nAkBCl+kaIABlDgB2TyYvNop2DHKdLj1/NFVqspxg2OZ+PFpcYWZnhIJpNR2YTS7fppI9chxGGoVaoF2ufGAA155kiYAC/2UFf45V9DrsDiW5oJd74PXz3GvbB7G78me4NBYTlZ6E2U9RUQ8ib2W2G7NyQAh2rA/0v9oVbFMOjHaovp4E0kADIUXrdHj7UphaDMNVmFI8uPbLTNHh1j0yweg9TorA3i9QVG++wJ8mFW/+qCMhcw4M5MkJKhbohEQSTdiENir/hkBDgmH2Mb76kLUpy72LBbuQmbzTxb/72PRSqIpMLQzaCbmMGlpUaK3vgZETvUZjjBgt4pMDzki6KjZ67bXhp8FsFoAD/VLPF3juH6/5ulXqmMKP3VJts/ZTzhvn7yRV+YA5YjXUdzUh3pYbraURIsrXvJKzp9+bLzLh2OX/8XRU3bPfLgAEBhwvU9CUEiZ5+3jwSEl3u7rF7ADfUCFeSc/Tb46brgtZNf06ps56C9GKa/c6pSIXEKFjm6AyptXkCeIA9/MdioBEZcYyMrEYkW+gUFGCAaoSSyQmdTmydElc514U3inTM9FETZNTCFmxK/5VHnbEgLKBiDCXL6VDqr8pqBe5DzPxtoAZXIwrDh5AAAABgAAAAAAAAAAAAAAAA4ILwb/ZX2UMQy4zosNmgRUHYBSAAAAAAABqd0BAgAAAAAAAAAAAAAAALMfZqo8HnhTY/CHWht04nuF/WbHAAYSV0FWQVgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABXcmFwcGVkIEFWQVgAAAAAAAAAAAAAAAAAAAAAAAAAAA== --gs cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
const wavaxAttestation =
"01000000000100b1cc54a6b6a3ee8baadc39f7f59b6074ae647d811ffb3deac1036231dfdc26f02a0e6fa6033f549efc358e7443d979bd261ab3ad8f74ce6f90c14cb136a6832701657230ac3879000000060000000000000000000000000e082f06ff657d94310cb8ce8b0d9a04541d8052000000000001a9dd0102000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c700061257415641580000000000000000000000000000000000000000000000000000005772617070656420415641580000000000000000000000000000000000000000";
const txhash = await submitTokenBridgeVAA(wavaxAttestation);
console.log(
`Created WAVAX https://finder.terraclassic.community/mainnet/tx/${txhash}`
);
}
}
const wavaxAddress =
"terra1kw3u6nyle39qhj4s725rg2lczdtscqkhfcrg33jvup00cm6ae3uqw9ewvw";
async function step8b() {
// WAVAX transfer in
// worm edit-vaa -v AQAAAAMNAOoKGMdKp40UoEoAQ0qZXVPawkpV4yZ4qCN7XC9KYV2VLLDcitjwRZ0rWh2xzFZVAntuxTSsl7sXXs5bkdKDNVEBAithN161Hu4+xIo7ADSNMTehvD70vg3bjB7/5cDt+ieYWZNeyhPgGlA/31y2vS5xtRGUOgCHoHVyDGTJ7RqRCpgBA6Z/g3R64BdryeqYDbGytx1uSNT7rbqadNkVb0BZvaJFAE5ITG9GW2bOZIAicg8iOcZw7WYa8a6vmuubKfzYp78BBI8OTu8tW72PzIspTYjEwinm7LpfgQ51ERIkAtFug2tmGZTwGiNRXoZeo9m1XpLgR/U01y6VQrIqUJasamVn6XwABv6qxtZkBfgT0T3nu6HEwv88CYXT/FXAYu/7HOVII/OneQQxIT9OS2BTiuMIWVcuvZ2qP2sdGhtOcX1f4crPCMcAB0yP5J7sQu+D2LDUsYjdELtMtj4KeWtjCkCBR6skWe/8IuRndXFvllNo0GRsB6A3XFnXReadRp5jH4A6t5UzS1UBCG6rkvPMMt7oUdSZBt9Lytd554Q5E310keqAB8+SXFumUY1y17U6KSgfTKgnWZBrTINj1RUw1ew8hElFziUKLDMADZE1+TeCwS+7W/59kz2mxBOgYa63j4pwdsB33BRGRfw9aYSQ3mkszyH+88bIKgjWzhJvRjs622L20QnBIbs5EAABDtf8OfUwbyAeOKM5D6m9pkDMlmz0hNwLa1Iuk2sQjLJsLRtbFYXScfgErmSkIgGGoMRtMt7Hk9pkebaD92skGOkADy10mYk73Lm360c2DZsnTCYsv0rKQ+MMrMverp9d8K5uALqZ3huvhJmTKtpNG/Dpzjsolk2aADcPHuEJudy4ZFEBEA19NY1c97Qo+VMwx3E/B6sEFszT8L93zPYhjBkWsuY9HwSsogKKb84170DApcKiXuz2jhw4e/eStObBBn7gc0AAESW+7FjIHqqFL35z/T+Mpq8lrvaPwiZJnKaMipWzre4RIRrBx/UKhGaADniFOOCc1J2/KMwH6E5WXFbO9pexAkoBEpxYKgkPcldCBmwI96Rk6lul3Rflkj3FrJvVrzJumyBffW+NwSdvFP0QltmzVEN39K9prXttF5bTlxcxaxpFU58AZXI6igwiAAAABgAAAAAAAAAAAAAAAA4ILwb/ZX2UMQy4zosNmgRUHYBSAAAAAAABqe0BAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkAAAAAAAAAAAAAAAAsx9mqjweeFNj8IdaG3Tie4X9ZscABgAAAAAAAAAAAAAAAD1aJY70jTtGjw8Tlz+RsqmlzFPYAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== --gs cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
const wavaxTransfer =
"0100000000010044dd5206ac105e99c39b2a368e510978f1e18cf61bfbfac399244c9bbcf23b3e61bd5e6ca098855263745890bae05e6450a9d4ccdb395ecd01471e5867db738a0065723a8a0c22000000060000000000000000000000000e082f06ff657d94310cb8ce8b0d9a04541d8052000000000001a9ed01010000000000000000000000000000000000000000000000000000000000000064000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c700060000000000000000000000003d5a258ef48d3b468f0f13973f91b2a9a5cc53d800030000000000000000000000000000000000000000000000000000000000000000";
const txhash = await submitTokenBridgeVAA(wavaxTransfer);
console.log(
`Redeemed WAVAX https://finder.terraclassic.community/mainnet/tx/${txhash}`
);
}
async function step8c() {
// WAVAX transfer out
const amount = "100";
const tx = await wallet.createAndSignTx({
msgs: [
new MsgExecuteContract(
wallet.key.accAddress,
wavaxAddress,
{
increase_allowance: {
spender: addressTokenBridge,
amount,
expires: {
never: {},
},
},
},
{}
),
new MsgExecuteContract(
wallet.key.accAddress,
addressTokenBridge,
{
initiate_transfer: {
asset: {
amount,
info: {
token: {
contract_addr: wavaxAddress,
},
},
},
recipient_chain: 4,
recipient: Buffer.from(
"0000000000000000000000000000000000000000000000000000000000000000",
"hex"
).toString("base64"),
fee: "0",
nonce: 0,
},
},
{}
),
],
memo: "",
fee: new Fee(1000000, { uluna: 50_000_000 }),
});
const response = await broadcastAndWait(terra, tx);
console.log(
`Transferred WAVAX https://finder.terraclassic.community/mainnet/tx/${response?.txhash}`
);
}
async function step9() {
{
// Fantom mainnet token bridge registration
// worm generate registration -c fantom -a 7C9Fc5741288cDFdD83CeB07f3ea7e22618D79D2 -m TokenBridge -g cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
const registerAvalanche =
"01000000000100f4644a32805b1e24eb40d91ffa05196bfa2783c74448070661701db4168a3e55787e1bd1bc4b300309b85990a4a75c8f7ff420c90b5d5a853076e413a02ef98c000000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000004eadf0f00000000000000000000000000000000000000000000546f6b656e427269646765010000000a0000000000000000000000007c9fc5741288cdfdd83ceb07f3ea7e22618d79d2";
const txhash = await submitTokenBridgeVAA(registerAvalanche);
console.log(
`Registered Fantom https://finder.terraclassic.community/mainnet/tx/${txhash}`
);
}
{
// WFTM attestation
// worm edit-vaa -v AQAAAAMNAGZLTJJ7k9izhrCiPU4vVY7CYp2c5592bObi2AKLGlj4CCxEGiQMva1F92+4kiX96CQoHG6iGSLX/uIwWZ0LdxkBAkq/rbbsqsk/Ax1gcowejzzJXgvfuSReU/Ob2sj4om2UY/L5R9b15jNb9uFexIkXitEaMRAzy0pnX1dBHx8ATfkAAyLgNbwTYAuA+sY+99cvm+e7r4V98IgXC4abG18t2K1nR9wxLpUMzNVPqDXVO/nDzvdQGqmHuhsC6IcwBT4CrCIABGWCArnx4DzWkS1Nsr88S7OvVOAWvn7AxTlVo0HT7SSwYhb7TUP2vBwJbA6mC0lK0UeBM3P4yoAKiFwSgqYPaZwABmewrAPd+r8uBGivWWfgsV5MbqwDEPy34mf+4LyhKtlifQc/QA3Mm+ttykD4SBp4ylAbvuwLBu8lqGrlzb/MoIYBBxLvs7gB2//Qx0qbsf7Ujau3g3Ipl1G2KTid1Xbn+5JDXbeJYEZQ3r2oiMB9N7HUNlldVPf3Nxn3oaZRHUvHYJkACzsVuZ0g4d2I2/XlLoanV90ElTFPjfmfe6Yp2Sol4mqOcz1Y+7QNmMm7iaKX9V7zRxvr/h6TWLip/P+mHjHRoywADGY6Vws8S5crT4U38OQoMEt9zFrBi1fttzdzv5P4BBKkWqUGP5ma2QyM39i6sussCgeI5qJae4ro3xXos5Qs218BDfgNXK8IojRwZoL8H+JKVOBv2qVN8rsbIwAN42TM3olCAliJYhhou8iZyjdeztmQRQl+7YESz8DVgLRNYhfPRDQADlQw39Txk19urWtjwb5LgVIWKea8AQqyocY2f3hJqbt9HFzWhR6Ho+gJ/wr7OnVoe9IIn4W5mvyiJYOLrmmNhzgBEEIZ8n6Qevl1+dZR2bdZHn6Cqdk6/UiPcyWmTHrMC8YKD+tKj3eRPHDDldnEJ23tsrtLhiCZm2OhiONefWCv9q8BEQCzPrgDqun4qbYMwAP8Bw8e22fJ5AnCOj6EksJEeYO7Kgwiijbc12wHosCaFD5YZXTqGPJ9zot1XH1tcFzYePABEtMHLrXStHqUtHUaR2KtRTKOL71Yy89SY8lEe70JJw9lVMJggnBVTPAdjic/frvLXFOZWgHmVYxz3fCIJWb0EboAZXMyeXI3AAAACgAAAAAAAAAAAAAAAHyfxXQSiM392DzrB/PqfiJhjXnSAAAAAAAAe34BAgAAAAAAAAAAAAAAACG+Nw1TEvRMtCzjd7ybigzvGkyDAAoSV0ZUTQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABXcmFwcGVkIEZhbnRvbQAAAAAAAAAAAAAAAAAAAAAAAA== --gs cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0
const wftmAttestation =
"01000000000100bc136a00a448e2cc01ae1b81ca9d37a301a98fa906893b0735817b79d614b8bb3ede50f3d125bf581bff3640abc4b9ca83171c5e7ff7963f4a9a5517b6cb0009006573327972370000000a0000000000000000000000007c9fc5741288cdfdd83ceb07f3ea7e22618d79d20000000000007b7e010200000000000000000000000021be370d5312f44cb42ce377bc9b8a0cef1a4c83000a125746544d00000000000000000000000000000000000000000000000000000000577261707065642046616e746f6d000000000000000000000000000000000000";
const txhash = await submitTokenBridgeVAA(wftmAttestation);
console.log(
`Created WFTM https://finder.terraclassic.community/mainnet/tx/${txhash}`
);
}
}
async function step10() {
// skipping step10 as already covered by 8
}
async function step11() {
const tx = await wallet.createAndSignTx({
msgs: [
new MsgExecuteContract(
wallet.key.accAddress,
addressTokenBridge,
{
create_asset_meta: {
asset_info: {
native_token: { denom: "uluna" },
},
nonce: 0,
},
},
{}
),
],
memo: "",
fee: new Fee(1000000, { uluna: 50_000_000 }),
});
const response = await broadcastAndWait(terra, tx);
console.log(
`Attested uluna https://finder.terraclassic.community/mainnet/tx/${response?.txhash}`
);
}
async function step12() {
{
const tx = await wallet.createAndSignTx({
msgs: [
new MsgExecuteContract(
wallet.key.accAddress,
addressTokenBridge,
{
deposit_tokens: {},
},
{ uluna: 10000 }
),
],
memo: "",
fee: new Fee(200000, { uluna: 10_000_000 }),
});
const response = await broadcastAndWait(terra, tx);
console.log(
`Deposted uluna https://finder.terraclassic.community/mainnet/tx/${response?.txhash}`
);
}
{
const tx = await wallet.createAndSignTx({
msgs: [
new MsgExecuteContract(
wallet.key.accAddress,
addressTokenBridge,
{
withdraw_tokens: {
asset: {
native_token: {
denom: "uluna",
},
},
},
},
{}
),
],
memo: "",
fee: new Fee(200000, { uluna: 10_000_000 }),
});
const response = await broadcastAndWait(terra, tx);
console.log(
`Withdrew uluna https://finder.terraclassic.community/mainnet/tx/${response?.txhash}`
);
}
}
async function step13() {
{
const tx = await wallet.createAndSignTx({
msgs: [
new MsgExecuteContract(
wallet.key.accAddress,
addressTokenBridge,
{
deposit_tokens: {},
},
{ uluna: 10000 }
),
new MsgExecuteContract(
wallet.key.accAddress,
addressTokenBridge,
{
initiate_transfer: {
asset: {
amount: "10000",
info: {
native_token: {
denom: "uluna",
},
},
},
recipient_chain: 2,
recipient: Buffer.from(
"0000000000000000000000000000000000000000000000000000000000000000",
"hex"
).toString("base64"),
fee: "0",
nonce: 1,
},
},
{} // no fee?
// { uluna: 10050 } // fee + tax
),
],
memo: "",
fee: new Fee(500000, { uluna: 20_000_000 }),
});
const response = await broadcastAndWait(terra, tx);
console.log(
`Sent uluna https://finder.terraclassic.community/mainnet/tx/${response?.txhash}`
);
}
// 10000 uluna from avax to terra classic
{
const transferVAA =
"010000000001002e1a7f786c42d41047bc4a6c55c2210a00dbeae45d43ead884eb42c163a7d72708a089c1e93779adbcf0603fac904a77c47e0c49cd0663ab250c434f6ceeb1f600652719abea95000000060000000000000000000000000e082f06ff657d94310cb8ce8b0d9a04541d80520000000000018b9401010000000000000000000000000000000000000000000000000000000000002710010000000000000000000000000000000000000000000000000000756c756e6100030000000000000000000000003d5a258ef48d3b468f0f13973f91b2a9a5cc53d800030000000000000000000000000000000000000000000000000000000000000000";
const txhash = await submitTokenBridgeVAA(transferVAA);
console.log(
`Redeemed uluna https://finder.terraclassic.community/mainnet/tx/${txhash}`
);
}
}
async function step14() {
try {
await submitTokenBridgeVAA(registerAvalanche);
} catch (e) {}
}
const cw20with20ByteAddress = "terra1hj8de24c3yqvcsv9r8chr03fzwsak3hgd8gv3m";
async function step15a() {
const tx = await wallet.createAndSignTx({
msgs: [
new MsgExecuteContract(
wallet.key.accAddress,
addressTokenBridge,
{
create_asset_meta: {
asset_info: {
token: {
contract_addr: cw20with20ByteAddress,
},
},
nonce: 0,
},
},
{}
),
],
memo: "",
fee: new Fee(1000000, { uluna: 50_000_000 }),
});
const response = await broadcastAndWait(terra, tx);
console.log(
`Attested ${cw20with20ByteAddress} https://finder.terraclassic.community/mainnet/tx/${response?.txhash}`
);
}
async function step15b() {
const amount = "100";
const tx = await wallet.createAndSignTx({
msgs: [
new MsgExecuteContract(
wallet.key.accAddress,
cw20with20ByteAddress,
{
increase_allowance: {
spender: addressTokenBridge,
amount,
expires: {
never: {},
},
},
},
{}
),
new MsgExecuteContract(
wallet.key.accAddress,
addressTokenBridge,
{
initiate_transfer: {
asset: {
amount,
info: {
token: {
contract_addr: cw20with20ByteAddress,
},
},
},
recipient_chain: 4,
recipient: Buffer.from(
"0000000000000000000000000000000000000000000000000000000000000000",
"hex"
).toString("base64"),
fee: "0",
nonce: 0,
},
},
{}
),
],
memo: "",
fee: new Fee(1000000, { uluna: 50_000_000 }),
});
const response = await broadcastAndWait(terra, tx);
console.log(
`Transferred ${cw20with20ByteAddress} https://finder.terraclassic.community/mainnet/tx/${response?.txhash}`
);
}
async function step15c() {
const returnTransfer =
"010000000001009b0cf0b08f933c518246235e5b43d33d20de3ecdd7cfb364ee4dd5b29dc14fb216aefdbd0d948eec506eb18ff348675a353c07e3ee244f224b2461b6c7983c650065723a8a0c22000000060000000000000000000000000e082f06ff657d94310cb8ce8b0d9a04541d8052000000000001a9ed01010000000000000000000000000000000000000000000000000000000000000064000000000000000000000000bc8edcaab88900cc418519f171be2913a1db46e800030000000000000000000000003d5a258ef48d3b468f0f13973f91b2a9a5cc53d800030000000000000000000000000000000000000000000000000000000000000000";
const txhash = await submitTokenBridgeVAA(returnTransfer);
console.log(
`Redeemed ${cw20with20ByteAddress} https://finder.terraclassic.community/mainnet/tx/${txhash}`
);
}
const cw20with32ByteAddress =
"terra1uac8wsrpm4xtwn7qx3rwz602ztsc4qcd9m8rkhx24ywqsxkpvlfq5ywat8";
async function step16prime() {
const fileName = "cw20_base.wasm";
const newTokenCodeId = await deployCode(fileName);
console.log(`New test token code ID: ${newTokenCodeId}`);
existingCodeIds[fileName] = newTokenCodeId;
const addressTestToken = await instantiate(
fileName,
{
name: "TEST",
symbol: "TST",
decimals: 6,
initial_balances: [
{
address: wallet.key.accAddress,
amount: "100000000",
},
],
mint: null,
},
"testToken"
);
console.log(
`New test token instantiated https://finder.terraclassic.community/mainnet/address/${addressTestToken}`
);
}
async function step16a() {
const tx = await wallet.createAndSignTx({
msgs: [
new MsgExecuteContract(
wallet.key.accAddress,
addressTokenBridge,
{
create_asset_meta: {
asset_info: {
token: {
contract_addr: cw20with32ByteAddress,
},
},
nonce: 0,
},
},
{}
),
],
memo: "",
fee: new Fee(1000000, { uluna: 50_000_000 }),
});
const response = await broadcastAndWait(terra, tx);
console.log(
`Attested ${cw20with32ByteAddress} https://finder.terraclassic.community/mainnet/tx/${response?.txhash}`
);
}
async function step16b() {
const amount = "100";
const tx = await wallet.createAndSignTx({
msgs: [
new MsgExecuteContract(
wallet.key.accAddress,
cw20with32ByteAddress,
{
increase_allowance: {
spender: addressTokenBridge,
amount,
expires: {
never: {},
},
},
},
{}
),
new MsgExecuteContract(
wallet.key.accAddress,
addressTokenBridge,
{
initiate_transfer: {
asset: {
amount,
info: {
token: {
contract_addr: cw20with32ByteAddress,
},
},
},
recipient_chain: 4,
recipient: Buffer.from(
"0000000000000000000000000000000000000000000000000000000000000000",
"hex"
).toString("base64"),
fee: "0",
nonce: 0,
},
},
{}
),
],
memo: "",
fee: new Fee(1000000, { uluna: 50_000_000 }),
});
const response = await broadcastAndWait(terra, tx);
console.log(
`Transferred ${cw20with32ByteAddress} https://finder.terraclassic.community/mainnet/tx/${response?.txhash}`
);
}
async function step16c() {
const returnTransfer =
"010000000001004571e9f5012e31e7674d7e86adbcea5f3cfdbdef8ad1c95f46377144db94a4e77ecb390b4f1c1b01825b09bfbf89bb5597b45731d14c916db7b1817bbe0820000165723a8a0c22000000060000000000000000000000000e082f06ff657d94310cb8ce8b0d9a04541d8052000000000001a9ed01010000000000000000000000000000000000000000000000000000000000000064e770774061dd4cb74fc03446e169ea12e18a830d2ece3b5ccaa91c081ac167d200030000000000000000000000003d5a258ef48d3b468f0f13973f91b2a9a5cc53d800030000000000000000000000000000000000000000000000000000000000000000";
const txhash = await submitTokenBridgeVAA(returnTransfer);
console.log(
`Redeemed ${cw20with32ByteAddress} https://finder.terraclassic.community/mainnet/tx/${txhash}`
);
}
async function main() {
// await step1();
console.log(
`Core bridge: https://finder.terraclassic.community/mainnet/address/${addressCoreBridge}`
);
console.log(
`Token bridge: https://finder.terraclassic.community/mainnet/address/${addressTokenBridge}`
);
// await step2();
// await step3();
// await step4();
// await step5();
// console.log(`New core bridge code ID: ${newCodeIdCoreBridge}`);
// console.log(`New token bridge code ID: ${newCodeIdTokenBridge}`);
// STOP HERE AND EDIT STEP 6 (also update the addresses and code IDs)
// await step6();
// await step7();
// await step8a();
// STOP HERE AND GATHER WAVAX ADDRESS
// await step8b();
// await step8c();
// await step9();
// await step10();
// await step11();
// await step12();
// await step13();
// await step14();
// await step15a();
// await step15b();
// await step15c();
// await step16prime();
// await step16a();
// await step16b();
// await step16c();
}
main();