174 lines
4.8 KiB
JavaScript
174 lines
4.8 KiB
JavaScript
import { LCDClient, MnemonicKey } from "@terra-money/terra.js";
|
|
import {
|
|
MsgInstantiateContract,
|
|
MsgStoreCode,
|
|
} from "@terra-money/terra.js";
|
|
import { readFileSync, readdirSync } from "fs";
|
|
import { Bech32, toHex } from "@cosmjs/encoding";
|
|
import { zeroPad } from "ethers/lib/utils.js";
|
|
|
|
/*
|
|
NOTE: Only append to this array: keeping the ordering is crucial, as the
|
|
contracts must be imported in a deterministic order so their addresses remain
|
|
deterministic.
|
|
*/
|
|
const artifacts = [
|
|
"wormhole.wasm",
|
|
"pyth_bridge.wasm",
|
|
];
|
|
|
|
/* Check that the artifact folder contains all the wasm files we expect and nothing else */
|
|
|
|
const actual_artifacts = readdirSync("../artifacts/").filter((a) =>
|
|
a.endsWith(".wasm")
|
|
);
|
|
|
|
const missing_artifacts = artifacts.filter(
|
|
(a) => !actual_artifacts.includes(a)
|
|
);
|
|
if (missing_artifacts.length) {
|
|
console.log(
|
|
"Error during terra deployment. The following files are expected to be in the artifacts folder:"
|
|
);
|
|
missing_artifacts.forEach((file) => console.log(` - ${file}`));
|
|
console.log(
|
|
"Hint: the deploy script needs to run after the contracts have been built."
|
|
);
|
|
console.log(
|
|
"External binary blobs need to be manually added in tools/Dockerfile."
|
|
);
|
|
process.exit(1);
|
|
}
|
|
|
|
const unexpected_artifacts = actual_artifacts.filter(
|
|
(a) => !artifacts.includes(a)
|
|
);
|
|
if (unexpected_artifacts.length) {
|
|
console.log(
|
|
"Error during terra deployment. The following files are not expected to be in the artifacts folder:"
|
|
);
|
|
unexpected_artifacts.forEach((file) => console.log(` - ${file}`));
|
|
console.log("Hint: you might need to modify tools/deploy.js");
|
|
process.exit(1);
|
|
}
|
|
|
|
/* Set up terra client & wallet */
|
|
|
|
const terra = new LCDClient({
|
|
URL: "http://localhost:1317",
|
|
chainID: "localterra",
|
|
});
|
|
|
|
const wallet = terra.wallet(
|
|
new MnemonicKey({
|
|
mnemonic:
|
|
"notice oak worry limit wrap speak medal online prefer cluster roof addict wrist behave treat actual wasp year salad speed social layer crew genius",
|
|
})
|
|
);
|
|
|
|
await wallet.sequence();
|
|
|
|
/* Deploy artifacts */
|
|
|
|
const codeIds = {};
|
|
for (const file of artifacts) {
|
|
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")
|
|
);
|
|
|
|
try {
|
|
const tx = await wallet.createAndSignTx({
|
|
msgs: [store_code],
|
|
memo: "",
|
|
});
|
|
|
|
const rs = await terra.tx.broadcast(tx);
|
|
const ci = /"code_id","value":"([^"]+)/gm.exec(rs.raw_log)[1];
|
|
codeIds[file] = parseInt(ci);
|
|
} catch (e) {
|
|
console.log(`${e}`);
|
|
}
|
|
}
|
|
|
|
console.log(codeIds);
|
|
|
|
/* Instantiate contracts.
|
|
*
|
|
* We instantiate the core contracts here (i.e. wormhole itself and the bridge contracts).
|
|
* The wrapped asset contracts don't need to be instantiated here, because those
|
|
* will be instantiated by the on-chain bridge contracts on demand.
|
|
* */
|
|
|
|
// Governance constants defined by the Wormhole spec.
|
|
const govChain = 1;
|
|
const govAddress =
|
|
"0000000000000000000000000000000000000000000000000000000000000004";
|
|
|
|
async function instantiate(contract, inst_msg, label) {
|
|
var address;
|
|
await wallet
|
|
.createAndSignTx({
|
|
msgs: [
|
|
new MsgInstantiateContract(
|
|
wallet.key.accAddress,
|
|
wallet.key.accAddress,
|
|
codeIds[contract],
|
|
inst_msg,
|
|
undefined,
|
|
label
|
|
),
|
|
],
|
|
memo: "",
|
|
})
|
|
.then((tx) => terra.tx.broadcast(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;
|
|
}
|
|
|
|
// Instantiate contracts. NOTE: Only append at the end, the ordering must be
|
|
// deterministic for the addresses to work
|
|
|
|
const addresses = {};
|
|
|
|
addresses["wormhole.wasm"] = await instantiate("wormhole.wasm", {
|
|
gov_chain: govChain,
|
|
gov_address: Buffer.from(govAddress, "hex").toString("base64"),
|
|
guardian_set_expirity: 86400,
|
|
initial_guardian_set: {
|
|
addresses: [
|
|
{
|
|
bytes: Buffer.from(
|
|
"beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe",
|
|
"hex"
|
|
).toString("base64"),
|
|
},
|
|
],
|
|
expiration_time: 0,
|
|
},
|
|
}, "wormhole");
|
|
|
|
const pythEmitterAddress =
|
|
"71f8dcb863d176e2c420ad6610cf687359612b6fb392e0642b0ca6b1f186aa3b";
|
|
const pythChain = 1;
|
|
|
|
addresses["pyth_bridge.wasm"] = await instantiate("pyth_bridge.wasm", {
|
|
wormhole_contract: addresses["wormhole.wasm"],
|
|
pyth_emitter: Buffer.from(pythEmitterAddress, "hex").toString(
|
|
"base64"
|
|
),
|
|
pyth_emitter_chain: pythChain,
|
|
}, "pyth");
|
|
|
|
// 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));
|
|
}
|