Upgrade contract & fix deployment script (#447)
* merge * stuff * gr * config * config * config * config * config * config * config * cleanup * add commands * cleaunp * fix * use u64 Co-authored-by: Jayant Krishnamurthy <jkrishnamurthy@jumptrading.com> Co-authored-by: Jayant Krishnamurthy <jayant@jumpcrypto.com>
This commit is contained in:
parent
6833f41424
commit
cdf99f4c60
|
@ -21,7 +21,7 @@ First, build the contracts within [the current directory](./):
|
|||
bash build.sh
|
||||
```
|
||||
|
||||
This command will build and save the Pyth contract in the `artifact` directory.
|
||||
This command will build and save the Pyth contract in the `artifacts` directory.
|
||||
|
||||
Then, to deploy the Pyth contract (`pyth_cosmwasm.wasm`), run the following command in the `tools` directory:
|
||||
|
||||
|
|
|
@ -34,8 +34,10 @@ use {
|
|||
entry_point,
|
||||
has_coins,
|
||||
to_binary,
|
||||
Addr,
|
||||
Binary,
|
||||
Coin,
|
||||
CosmosMsg,
|
||||
Deps,
|
||||
DepsMut,
|
||||
Env,
|
||||
|
@ -46,6 +48,7 @@ use {
|
|||
Response,
|
||||
StdResult,
|
||||
Timestamp,
|
||||
WasmMsg,
|
||||
WasmQuery,
|
||||
},
|
||||
p2w_sdk::BatchPriceAttestation,
|
||||
|
@ -67,9 +70,19 @@ use {
|
|||
},
|
||||
};
|
||||
|
||||
/// Migration code that runs once when the contract is upgraded. On upgrade, the migrate
|
||||
/// function in the *new* code version is run, which allows the new code to update the on-chain
|
||||
/// state before any of its other functions are invoked.
|
||||
///
|
||||
/// After the upgrade is complete, the code in this function can be deleted (and replaced with
|
||||
/// different code for the next migration).
|
||||
///
|
||||
/// Most upgrades won't require any special migration logic. In those cases,
|
||||
/// this function can safely be implemented as:
|
||||
/// `Ok(Response::default())`
|
||||
#[cfg_attr(not(feature = "library"), entry_point)]
|
||||
pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> StdResult<Response> {
|
||||
Ok(Response::new())
|
||||
Ok(Response::default())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "library"), entry_point)]
|
||||
|
@ -182,9 +195,11 @@ fn execute_governance_instruction(
|
|||
}
|
||||
|
||||
let response = match instruction.action {
|
||||
UpgradeContract { .. } => {
|
||||
// FIXME: implement this
|
||||
Err(PythContractError::InvalidGovernancePayload)?
|
||||
UpgradeContract { code_id } => {
|
||||
if instruction.target_chain_id == 0 {
|
||||
Err(PythContractError::InvalidGovernancePayload)?
|
||||
}
|
||||
upgrade_contract(&env.contract.address, code_id)?
|
||||
}
|
||||
AuthorizeGovernanceDataSourceTransfer { claim_vaa } => {
|
||||
let parsed_claim_vaa = parse_vaa(deps.branch(), env.block.time.seconds(), &claim_vaa)?;
|
||||
|
@ -286,6 +301,20 @@ fn transfer_governance(
|
|||
}
|
||||
}
|
||||
|
||||
/// Upgrades the contract at `address` to `new_code_id` (by sending a `Migrate` message). The
|
||||
/// migration will fail unless this contract is the admin of the contract being upgraded.
|
||||
/// (Typically, `address` is this contract's address, and the contract is its own admin.)
|
||||
fn upgrade_contract(address: &Addr, new_code_id: u64) -> StdResult<Response> {
|
||||
Ok(Response::new()
|
||||
.add_message(CosmosMsg::Wasm(WasmMsg::Migrate {
|
||||
contract_addr: address.to_string(),
|
||||
new_code_id,
|
||||
msg: to_binary(&MigrateMsg {})?,
|
||||
}))
|
||||
.add_attribute("action", "upgrade_contract")
|
||||
.add_attribute("new_code_id", format!("{new_code_id}")))
|
||||
}
|
||||
|
||||
/// Check that `vaa` is from a valid data source (and hence is a legitimate price update message).
|
||||
fn verify_vaa_from_data_source(state: &ConfigInfo, vaa: &ParsedVAA) -> StdResult<()> {
|
||||
let vaa_data_source = PythDataSource {
|
||||
|
|
|
@ -51,9 +51,9 @@ impl GovernanceModule {
|
|||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
|
||||
#[repr(u8)]
|
||||
pub enum GovernanceAction {
|
||||
UpgradeContract { address: [u8; 20] }, // 0
|
||||
UpgradeContract { code_id: u64 }, // 0
|
||||
AuthorizeGovernanceDataSourceTransfer { claim_vaa: Binary }, // 1
|
||||
SetDataSources { data_sources: Vec<PythDataSource> }, // 2
|
||||
SetDataSources { data_sources: Vec<PythDataSource> }, // 2
|
||||
// Set the fee to val * (10 ** expo)
|
||||
SetFee { val: u64, expo: u64 }, // 3
|
||||
// Set the default valid period to the provided number of seconds
|
||||
|
@ -92,9 +92,8 @@ impl GovernanceInstruction {
|
|||
|
||||
let action: Result<GovernanceAction, String> = match action_type {
|
||||
0 => {
|
||||
let mut address: [u8; 20] = [0; 20];
|
||||
bytes.read_exact(&mut address)?;
|
||||
Ok(GovernanceAction::UpgradeContract { address })
|
||||
let code_id = bytes.read_u64::<BigEndian>()?;
|
||||
Ok(GovernanceAction::UpgradeContract { code_id })
|
||||
}
|
||||
1 => {
|
||||
let mut payload: Vec<u8> = vec![];
|
||||
|
@ -161,10 +160,10 @@ impl GovernanceInstruction {
|
|||
buf.write_u8(self.module.to_u8())?;
|
||||
|
||||
match &self.action {
|
||||
GovernanceAction::UpgradeContract { address } => {
|
||||
GovernanceAction::UpgradeContract { code_id } => {
|
||||
buf.write_u8(0)?;
|
||||
buf.write_u16::<BigEndian>(self.target_chain_id)?;
|
||||
buf.write_all(address)?;
|
||||
buf.write_u64::<BigEndian>(*code_id)?;
|
||||
}
|
||||
GovernanceAction::AuthorizeGovernanceDataSourceTransfer { claim_vaa } => {
|
||||
buf.write_u8(1)?;
|
||||
|
|
|
@ -7,13 +7,10 @@ import {
|
|||
import { readFileSync } from "fs";
|
||||
import { Bech32, toHex } from "@cosmjs/encoding";
|
||||
import { zeroPad } from "ethers/lib/utils.js";
|
||||
import axios from "axios";
|
||||
import yargs from "yargs";
|
||||
import { hideBin } from "yargs/helpers";
|
||||
import assert from "assert";
|
||||
|
||||
export const TERRA_GAS_PRICES_URL = "https://fcd.terra.dev/v1/txs/gas_prices";
|
||||
|
||||
const argv = yargs(hideBin(process.argv))
|
||||
.option("network", {
|
||||
description: "Which network to deploy to",
|
||||
|
@ -64,38 +61,96 @@ const artifact = argv.artifact;
|
|||
const CONFIG = {
|
||||
mainnet: {
|
||||
terraHost: {
|
||||
URL: "https://lcd.terra.dev",
|
||||
chainID: "columbus-5",
|
||||
URL: "https://phoenix-lcd.terra.dev",
|
||||
chainID: "phoenix-1",
|
||||
name: "mainnet",
|
||||
},
|
||||
wormholeContract: "terra1dq03ugtd40zu9hcgdzrsq6z2z4hwhc9tqk2uy5",
|
||||
pythEmitterAddress:
|
||||
"6bb14509a612f01fbbc4cffeebd4bbfb492a86df717ebe92eb6df432a3f00a25",
|
||||
pyth_config: {
|
||||
wormhole_contract:
|
||||
"terra12mrnzvhx3rpej6843uge2yyfppfyd3u9c3uq223q8sl48huz9juqffcnh",
|
||||
data_sources: [
|
||||
{
|
||||
emitter: Buffer.from(
|
||||
"6bb14509a612f01fbbc4cffeebd4bbfb492a86df717ebe92eb6df432a3f00a25",
|
||||
"hex"
|
||||
).toString("base64"),
|
||||
chain_id: 1,
|
||||
},
|
||||
{
|
||||
emitter: Buffer.from(
|
||||
"f8cd23c2ab91237730770bbea08d61005cdda0984348f3f6eecb559638c0bba0",
|
||||
"hex"
|
||||
).toString("base64"),
|
||||
chain_id: 26,
|
||||
},
|
||||
],
|
||||
governance_source: {
|
||||
emitter: Buffer.from(
|
||||
"5635979a221c34931e32620b9293a463065555ea71fe97cd6237ade875b12e9e",
|
||||
"hex"
|
||||
).toString("base64"),
|
||||
chain_id: 1,
|
||||
},
|
||||
governance_source_index: 0,
|
||||
governance_sequence_number: 0,
|
||||
chain_id: 18,
|
||||
valid_time_period_secs: 60,
|
||||
fee: {
|
||||
amount: "1",
|
||||
denom: "uluna",
|
||||
},
|
||||
},
|
||||
},
|
||||
testnet: {
|
||||
terraHost: {
|
||||
URL: "https://bombay-lcd.terra.dev",
|
||||
chainID: "bombay-12",
|
||||
URL: "https://pisco-lcd.terra.dev",
|
||||
chainID: "pisco-1",
|
||||
name: "testnet",
|
||||
},
|
||||
wormholeContract: "terra1pd65m0q9tl3v8znnz5f5ltsfegyzah7g42cx5v",
|
||||
pythEmitterAddress:
|
||||
"f346195ac02f37d60d4db8ffa6ef74cb1be3550047543a4a9ee9acf4d78697b0",
|
||||
pyth_config: {
|
||||
wormhole_contract:
|
||||
"terra19nv3xr5lrmmr7egvrk2kqgw4kcn43xrtd5g0mpgwwvhetusk4k7s66jyv0",
|
||||
data_sources: [
|
||||
{
|
||||
emitter: Buffer.from(
|
||||
"f346195ac02f37d60d4db8ffa6ef74cb1be3550047543a4a9ee9acf4d78697b0",
|
||||
"hex"
|
||||
).toString("base64"),
|
||||
chain_id: 1,
|
||||
},
|
||||
{
|
||||
emitter: Buffer.from(
|
||||
"a27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b6",
|
||||
"hex"
|
||||
).toString("base64"),
|
||||
chain_id: 26,
|
||||
},
|
||||
],
|
||||
governance_source: {
|
||||
emitter: Buffer.from(
|
||||
"63278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c385",
|
||||
"hex"
|
||||
).toString("base64"),
|
||||
chain_id: 1,
|
||||
},
|
||||
governance_source_index: 0,
|
||||
governance_sequence_number: 0,
|
||||
chain_id: 18,
|
||||
valid_time_period_secs: 60,
|
||||
fee: {
|
||||
amount: "1",
|
||||
denom: "uluna",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const terraHost = CONFIG[argv.network].terraHost;
|
||||
const wormholeContract = CONFIG[argv.network].wormholeContract;
|
||||
const pythEmitterAddress = CONFIG[argv.network].pythEmitterAddress;
|
||||
|
||||
const pythConfig = CONFIG[argv.network].pyth_config;
|
||||
const lcd = new LCDClient(terraHost);
|
||||
|
||||
const feeDenoms = ["uluna"];
|
||||
|
||||
const gasPrices = await axios
|
||||
.get(TERRA_GAS_PRICES_URL)
|
||||
.then((result) => result.data);
|
||||
|
||||
const wallet = lcd.wallet(
|
||||
new MnemonicKey({
|
||||
mnemonic: argv.mnemonic,
|
||||
|
@ -124,22 +179,9 @@ if (argv.codeId !== undefined) {
|
|||
contract_bytes.toString("base64")
|
||||
);
|
||||
|
||||
const feeEstimate = await lcd.tx.estimateFee(
|
||||
wallet.key.accAddress,
|
||||
[store_code],
|
||||
{
|
||||
feeDenoms,
|
||||
gasPrices,
|
||||
}
|
||||
);
|
||||
|
||||
console.log("Deploy fee: ", feeEstimate.amount.toString());
|
||||
|
||||
const tx = await wallet.createAndSignTx({
|
||||
msgs: [store_code],
|
||||
feeDenoms,
|
||||
gasPrices,
|
||||
fee: feeEstimate,
|
||||
});
|
||||
|
||||
const rs = await lcd.tx.broadcast(tx);
|
||||
|
@ -166,7 +208,7 @@ if (argv.codeId !== undefined) {
|
|||
if (argv.instantiate) {
|
||||
console.log("Instantiating a contract");
|
||||
|
||||
async function instantiate(codeId, inst_msg) {
|
||||
async function instantiate(codeId, inst_msg, label) {
|
||||
var address;
|
||||
await wallet
|
||||
.createAndSignTx({
|
||||
|
@ -175,7 +217,9 @@ if (argv.instantiate) {
|
|||
wallet.key.accAddress,
|
||||
wallet.key.accAddress,
|
||||
codeId,
|
||||
inst_msg
|
||||
inst_msg,
|
||||
undefined,
|
||||
label
|
||||
),
|
||||
],
|
||||
})
|
||||
|
@ -199,13 +243,7 @@ if (argv.instantiate) {
|
|||
return address;
|
||||
}
|
||||
|
||||
const pythChain = 1;
|
||||
|
||||
const contractAddress = await instantiate(codeId, {
|
||||
wormhole_contract: wormholeContract,
|
||||
pyth_emitter: Buffer.from(pythEmitterAddress, "hex").toString("base64"),
|
||||
pyth_emitter_chain: pythChain,
|
||||
});
|
||||
const contractAddress = await instantiate(codeId, pythConfig, "pyth");
|
||||
|
||||
console.log(`Deployed Pyth contract at ${contractAddress}`);
|
||||
}
|
||||
|
@ -233,7 +271,6 @@ if (argv.migrate) {
|
|||
),
|
||||
],
|
||||
feeDenoms,
|
||||
gasPrices,
|
||||
});
|
||||
|
||||
const rs = await lcd.tx.broadcast(tx);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"main": "deploy.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
"deploy-pyth": "node deploy-pyth-bridge.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
|
|
Loading…
Reference in New Issue