From c04fe958599194792efe821601ab2055fabd5344 Mon Sep 17 00:00:00 2001 From: Reisen Date: Mon, 6 Sep 2021 08:27:27 +0000 Subject: [PATCH] terra/contracts: columbus-5 migration for wormhole Change-Id: I6772a49d3d667633b27d74eb7f349e01c849f505 --- terra/contracts-5/wormhole/Cargo.toml | 14 +- terra/contracts-5/wormhole/src/contract.rs | 217 ++++++++------------- terra/contracts-5/wormhole/src/error.rs | 1 - terra/contracts-5/wormhole/src/lib.rs | 3 - terra/contracts-5/wormhole/src/msg.rs | 7 +- terra/contracts-5/wormhole/src/state.rs | 54 ++--- 6 files changed, 119 insertions(+), 177 deletions(-) diff --git a/terra/contracts-5/wormhole/Cargo.toml b/terra/contracts-5/wormhole/Cargo.toml index 391fdd4c..b7464e6d 100644 --- a/terra/contracts-5/wormhole/Cargo.toml +++ b/terra/contracts-5/wormhole/Cargo.toml @@ -14,15 +14,15 @@ backtraces = ["cosmwasm-std/backtraces"] library = [] [dependencies] -cosmwasm-std = { version = "0.10.0" } -cosmwasm-storage = { version = "0.10.0" } -schemars = "0.7" +cosmwasm-std = { version = "0.16.0" } +cosmwasm-storage = { version = "0.16.0" } +schemars = "0.8.1" serde = { version = "1.0.103", default-features = false, features = ["derive"] } -cw20 = "0.2.2" -cw20-base = { version = "0.2.2", features = ["library"] } +cw20 = "0.8.0" +cw20-base = { version = "0.8.0", features = ["library"] } cw20-wrapped = { path = "../cw20-wrapped", features = ["library"] } thiserror = { version = "1.0.20" } -k256 = { version = "0.5.9", default-features = false, features = ["ecdsa"] } +k256 = { version = "0.9.4", default-features = false, features = ["ecdsa"] } sha3 = { version = "0.9.1", default-features = false } generic-array = { version = "0.14.4" } hex = "0.4.2" @@ -30,4 +30,4 @@ lazy_static = "1.4.0" [dev-dependencies] cosmwasm-vm = { version = "0.10.0", default-features = false, features = ["default-cranelift"] } -serde_json = "1.0" \ No newline at end of file +serde_json = "1.0" diff --git a/terra/contracts-5/wormhole/src/contract.rs b/terra/contracts-5/wormhole/src/contract.rs index c1859594..378cbb1e 100644 --- a/terra/contracts-5/wormhole/src/contract.rs +++ b/terra/contracts-5/wormhole/src/contract.rs @@ -1,18 +1,16 @@ use cosmwasm_std::{ + entry_point, has_coins, - log, to_binary, - Api, BankMsg, Binary, Coin, CosmosMsg, + Deps, + DepsMut, Env, - Extern, - HandleResponse, - HumanAddr, - InitResponse, - Querier, + MessageInfo, + Response, StdError, StdResult, Storage, @@ -25,11 +23,11 @@ use crate::{ }, error::ContractError, msg::{ + ExecuteMsg, GetAddressHexResponse, GetStateResponse, GuardianSetInfoResponse, - HandleMsg, - InitMsg, + InstantiateMsg, QueryMsg, }, state::{ @@ -59,7 +57,7 @@ use k256::{ Signature as RecoverableSignature, }, Signature, - VerifyKey, + VerifyingKey, }, EncodedPoint, }; @@ -71,6 +69,8 @@ use sha3::{ use generic_array::GenericArray; use std::convert::TryFrom; +type HumanAddr = String; + // Chain ID of Terra const CHAIN_ID: u16 = 3; @@ -78,11 +78,8 @@ const CHAIN_ID: u16 = 3; const FEE_AMOUNT: u128 = 10000; pub const FEE_DENOMINATION: &str = "uluna"; -pub fn init( - deps: &mut Extern, - _env: Env, - msg: InitMsg, -) -> StdResult { +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate(deps: DepsMut, _env: Env, msg: InstantiateMsg) -> StdResult { // Save general wormhole info let state = ConfigInfo { gov_chain: msg.gov_chain, @@ -91,41 +88,39 @@ pub fn init( guardian_set_expirity: msg.guardian_set_expirity, fee: Coin::new(FEE_AMOUNT, FEE_DENOMINATION), // 0.01 Luna (or 10000 uluna) fee by default }; - config(&mut deps.storage).save(&state)?; + config(deps.storage).save(&state)?; // Add initial guardian set to storage guardian_set_set( - &mut deps.storage, + deps.storage, state.guardian_set_index, &msg.initial_guardian_set, )?; - Ok(InitResponse::default()) + Ok(Response::default()) } -pub fn handle( - deps: &mut Extern, - env: Env, - msg: HandleMsg, -) -> StdResult { +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> StdResult { match msg { - HandleMsg::PostMessage { message, nonce } => { - handle_post_message(deps, env, &message.as_slice(), nonce) + ExecuteMsg::PostMessage { message, nonce } => { + handle_post_message(deps, env, info, &message.as_slice(), nonce) } - HandleMsg::SubmitVAA { vaa } => handle_submit_vaa(deps, env, vaa.as_slice()), + ExecuteMsg::SubmitVAA { vaa } => handle_submit_vaa(deps, env, info, vaa.as_slice()), } } /// Process VAA message signed by quardians -fn handle_submit_vaa( - deps: &mut Extern, +fn handle_submit_vaa( + deps: DepsMut, env: Env, + _info: MessageInfo, data: &[u8], -) -> StdResult { - let state = config_read(&deps.storage).load()?; +) -> StdResult { + let state = config_read(deps.storage).load()?; - let vaa = parse_and_verify_vaa(&deps.storage, data, env.block.time)?; - vaa_archive_add(&mut deps.storage, vaa.hash.as_slice())?; + let vaa = parse_and_verify_vaa(deps.storage, data, env.block.time.seconds())?; + vaa_archive_add(deps.storage, vaa.hash.as_slice())?; if state.gov_chain == vaa.emitter_chain && state.gov_address == vaa.emitter_address { if state.guardian_set_index != vaa.guardian_set_index { @@ -139,11 +134,7 @@ fn handle_submit_vaa( ContractError::InvalidVAAAction.std_err() } -fn handle_governance_payload( - deps: &mut Extern, - env: Env, - data: &Vec, -) -> StdResult { +fn handle_governance_payload(deps: DepsMut, env: Env, data: &Vec) -> StdResult { let gov_packet = GovernancePacket::deserialize(&data)?; let module = String::from_utf8(gov_packet.module).unwrap(); @@ -170,8 +161,8 @@ fn handle_governance_payload( /// Parses raw VAA data into a struct and verifies whether it contains sufficient signatures of an /// active guardian set i.e. is valid according to Wormhole consensus rules -fn parse_and_verify_vaa( - storage: &S, +fn parse_and_verify_vaa( + storage: &dyn Storage, data: &[u8], block_time: u64, ) -> StdResult { @@ -239,18 +230,14 @@ fn parse_and_verify_vaa( Ok(vaa) } -fn vaa_update_guardian_set( - deps: &mut Extern, - env: Env, - data: &Vec, -) -> StdResult { +fn vaa_update_guardian_set(deps: DepsMut, env: Env, data: &Vec) -> StdResult { /* Payload format 0 uint32 new_index 4 uint8 len(keys) 5 [][20]uint8 guardian addresses */ - let mut state = config_read(&deps.storage).load()?; + let mut state = config_read(deps.storage).load()?; let GuardianSetUpgrade { new_guardian_set_index, @@ -265,107 +252,72 @@ fn vaa_update_guardian_set( state.guardian_set_index = new_guardian_set_index; - guardian_set_set( - &mut deps.storage, - state.guardian_set_index, - &new_guardian_set, - )?; + guardian_set_set(deps.storage, state.guardian_set_index, &new_guardian_set)?; - config(&mut deps.storage).save(&state)?; + config(deps.storage).save(&state)?; - let mut old_guardian_set = guardian_set_get(&deps.storage, old_guardian_set_index)?; - old_guardian_set.expiration_time = env.block.time + state.guardian_set_expirity; - guardian_set_set(&mut deps.storage, old_guardian_set_index, &old_guardian_set)?; + let mut old_guardian_set = guardian_set_get(deps.storage, old_guardian_set_index)?; + old_guardian_set.expiration_time = env.block.time.seconds() + state.guardian_set_expirity; + guardian_set_set(deps.storage, old_guardian_set_index, &old_guardian_set)?; - Ok(HandleResponse { - messages: vec![], - log: vec![ - log("action", "guardian_set_change"), - log("old", old_guardian_set_index), - log("new", state.guardian_set_index), - ], - data: None, - }) + Ok(Response::new() + .add_attribute("action", "guardian_set_change") + .add_attribute("old", old_guardian_set_index.to_string()) + .add_attribute("new", state.guardian_set_index.to_string())) } -pub fn handle_set_fee( - deps: &mut Extern, - env: Env, - data: &Vec, -) -> StdResult { +pub fn handle_set_fee(deps: DepsMut, _env: Env, data: &Vec) -> StdResult { let set_fee_msg = SetFee::deserialize(&data)?; // Save new fees - let mut state = config_read(&mut deps.storage).load()?; + let mut state = config_read(deps.storage).load()?; state.fee = set_fee_msg.fee; - config(&mut deps.storage).save(&state)?; + config(deps.storage).save(&state)?; - Ok(HandleResponse { - messages: vec![], - log: vec![ - log("action", "fee_change"), - log("new_fee.amount", state.fee.amount), - log("new_fee.denom", state.fee.denom), - ], - data: None, - }) + Ok(Response::new() + .add_attribute("action", "fee_change") + .add_attribute("new_fee.amount", state.fee.amount.to_string()) + .add_attribute("new_fee.denom", state.fee.denom.to_string())) } -pub fn handle_transfer_fee( - deps: &mut Extern, - env: Env, - data: &Vec, -) -> StdResult { +pub fn handle_transfer_fee(deps: DepsMut, _env: Env, data: &Vec) -> StdResult { let transfer_msg = TransferFee::deserialize(&data)?; - Ok(HandleResponse { - messages: vec![CosmosMsg::Bank(BankMsg::Send { - from_address: env.contract.address, - to_address: deps.api.human_address(&transfer_msg.recipient)?, - amount: vec![transfer_msg.amount], - })], - log: vec![], - data: None, - }) + Ok(Response::new().add_message(CosmosMsg::Bank(BankMsg::Send { + to_address: deps.api.addr_humanize(&transfer_msg.recipient)?.to_string(), + amount: vec![transfer_msg.amount], + }))) } -fn handle_post_message( - deps: &mut Extern, +fn handle_post_message( + deps: DepsMut, env: Env, + info: MessageInfo, message: &[u8], nonce: u32, -) -> StdResult { - let state = config_read(&deps.storage).load()?; +) -> StdResult { + let state = config_read(deps.storage).load()?; let fee = state.fee; // Check fee - if !has_coins(env.message.sent_funds.as_ref(), &fee) { + if !has_coins(info.funds.as_ref(), &fee) { return ContractError::FeeTooLow.std_err(); } - let emitter = extend_address_to_32(&deps.api.canonical_address(&env.message.sender)?); + let emitter = extend_address_to_32(&deps.api.addr_canonicalize(&info.sender.as_str())?); + let sequence = sequence_read(deps.storage, emitter.as_slice()); + sequence_set(deps.storage, emitter.as_slice(), sequence + 1)?; - let sequence = sequence_read(&deps.storage, emitter.as_slice()); - sequence_set(&mut deps.storage, emitter.as_slice(), sequence + 1)?; - - Ok(HandleResponse { - messages: vec![], - log: vec![ - log("message.message", hex::encode(message)), - log("message.sender", hex::encode(emitter)), - log("message.chain_id", CHAIN_ID), - log("message.nonce", nonce), - log("message.sequence", sequence), - log("message.block_time", env.block.time), - ], - data: None, - }) + Ok(Response::new() + .add_attribute("message.message", hex::encode(message)) + .add_attribute("message.sender", hex::encode(emitter)) + .add_attribute("message.chain_id", CHAIN_ID.to_string()) + .add_attribute("message.nonce", nonce.to_string()) + .add_attribute("message.sequence", sequence.to_string()) + .add_attribute("message.block_time", env.block.time.seconds().to_string())) } -pub fn query( - deps: &Extern, - msg: QueryMsg, -) -> StdResult { +pub fn query(deps: Deps, msg: QueryMsg) -> StdResult { match msg { QueryMsg::GuardianSetInfo {} => to_binary(&query_guardian_set_info(deps)?), QueryMsg::VerifyVAA { vaa, block_time } => to_binary(&query_parse_and_verify_vaa( @@ -378,11 +330,9 @@ pub fn query( } } -pub fn query_guardian_set_info( - deps: &Extern, -) -> StdResult { - let state = config_read(&deps.storage).load()?; - let guardian_set = guardian_set_get(&deps.storage, state.guardian_set_index)?; +pub fn query_guardian_set_info(deps: Deps) -> StdResult { + let state = config_read(deps.storage).load()?; + let guardian_set = guardian_set_get(deps.storage, state.guardian_set_index)?; let res = GuardianSetInfoResponse { guardian_set_index: state.guardian_set_index, addresses: guardian_set.addresses, @@ -390,33 +340,28 @@ pub fn query_guardian_set_info( Ok(res) } -pub fn query_parse_and_verify_vaa( - deps: &Extern, +pub fn query_parse_and_verify_vaa( + deps: Deps, data: &[u8], block_time: u64, ) -> StdResult { - parse_and_verify_vaa(&deps.storage, data, block_time) + parse_and_verify_vaa(deps.storage, data, block_time) } // returns the hex of the 32 byte address we use for some address on this chain -pub fn query_address_hex( - deps: &Extern, - address: &HumanAddr, -) -> StdResult { +pub fn query_address_hex(deps: Deps, address: &HumanAddr) -> StdResult { Ok(GetAddressHexResponse { - hex: hex::encode(extend_address_to_32(&deps.api.canonical_address(&address)?)), + hex: hex::encode(extend_address_to_32(&deps.api.addr_canonicalize(&address)?)), }) } -pub fn query_state( - deps: &Extern, -) -> StdResult { - let state = config_read(&deps.storage).load()?; +pub fn query_state(deps: Deps) -> StdResult { + let state = config_read(deps.storage).load()?; let res = GetStateResponse { fee: state.fee }; Ok(res) } -fn keys_equal(a: &VerifyKey, b: &GuardianAddress) -> bool { +fn keys_equal(a: &VerifyingKey, b: &GuardianAddress) -> bool { let mut hasher = Keccak256::new(); let point: EncodedPoint = EncodedPoint::from(a); diff --git a/terra/contracts-5/wormhole/src/error.rs b/terra/contracts-5/wormhole/src/error.rs index 2975eafc..67603f5d 100644 --- a/terra/contracts-5/wormhole/src/error.rs +++ b/terra/contracts-5/wormhole/src/error.rs @@ -104,7 +104,6 @@ impl ContractError { pub fn std(&self) -> StdError { StdError::GenericErr { msg: format!("{}", self), - backtrace: None, } } diff --git a/terra/contracts-5/wormhole/src/lib.rs b/terra/contracts-5/wormhole/src/lib.rs index 9117b3f1..610d16ed 100644 --- a/terra/contracts-5/wormhole/src/lib.rs +++ b/terra/contracts-5/wormhole/src/lib.rs @@ -5,6 +5,3 @@ pub mod msg; pub mod state; pub use crate::error::ContractError; - -#[cfg(all(target_arch = "wasm32", not(feature = "library")))] -cosmwasm_std::create_entry_points!(contract); diff --git a/terra/contracts-5/wormhole/src/msg.rs b/terra/contracts-5/wormhole/src/msg.rs index 0bfc5c13..810aa92b 100644 --- a/terra/contracts-5/wormhole/src/msg.rs +++ b/terra/contracts-5/wormhole/src/msg.rs @@ -1,7 +1,6 @@ use cosmwasm_std::{ Binary, Coin, - HumanAddr, }; use schemars::JsonSchema; use serde::{ @@ -14,8 +13,10 @@ use crate::state::{ GuardianSetInfo, }; +type HumanAddr = String; + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct InitMsg { +pub struct InstantiateMsg { pub gov_chain: u16, pub gov_address: Binary, @@ -25,7 +26,7 @@ pub struct InitMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] -pub enum HandleMsg { +pub enum ExecuteMsg { SubmitVAA { vaa: Binary }, PostMessage { message: Binary, nonce: u32 }, } diff --git a/terra/contracts-5/wormhole/src/state.rs b/terra/contracts-5/wormhole/src/state.rs index e8abe94e..c0ce806f 100644 --- a/terra/contracts-5/wormhole/src/state.rs +++ b/terra/contracts-5/wormhole/src/state.rs @@ -1,6 +1,5 @@ use schemars::{ JsonSchema, - Set, }; use serde::{ Deserialize, @@ -11,7 +10,6 @@ use cosmwasm_std::{ Binary, CanonicalAddr, Coin, - HumanAddr, StdResult, Storage, Uint128, @@ -37,6 +35,8 @@ use sha3::{ Keccak256, }; +type HumanAddr = String; + pub static CONFIG_KEY: &[u8] = b"config"; pub static GUARDIAN_SET_KEY: &[u8] = b"guardian_set"; pub static SEQUENCE_KEY: &[u8] = b"sequence"; @@ -217,62 +217,62 @@ pub struct WormholeInfo { pub guardian_set_expirity: u64, } -pub fn config(storage: &mut S) -> Singleton { +pub fn config(storage: &mut dyn Storage) -> Singleton { singleton(storage, CONFIG_KEY) } -pub fn config_read(storage: &S) -> ReadonlySingleton { +pub fn config_read(storage: &dyn Storage) -> ReadonlySingleton { singleton_read(storage, CONFIG_KEY) } -pub fn guardian_set_set( - storage: &mut S, +pub fn guardian_set_set( + storage: &mut dyn Storage, index: u32, data: &GuardianSetInfo, ) -> StdResult<()> { - bucket(GUARDIAN_SET_KEY, storage).save(&index.to_be_bytes(), data) + bucket(storage, GUARDIAN_SET_KEY).save(&index.to_be_bytes(), data) } -pub fn guardian_set_get(storage: &S, index: u32) -> StdResult { - bucket_read(GUARDIAN_SET_KEY, storage).load(&index.to_be_bytes()) +pub fn guardian_set_get(storage: &dyn Storage, index: u32) -> StdResult { + bucket_read(storage, GUARDIAN_SET_KEY).load(&index.to_be_bytes()) } -pub fn sequence_set(storage: &mut S, emitter: &[u8], sequence: u64) -> StdResult<()> { - bucket(SEQUENCE_KEY, storage).save(emitter, &sequence) +pub fn sequence_set(storage: &mut dyn Storage, emitter: &[u8], sequence: u64) -> StdResult<()> { + bucket(storage, SEQUENCE_KEY).save(emitter, &sequence) } -pub fn sequence_read(storage: &S, emitter: &[u8]) -> u64 { - bucket_read(SEQUENCE_KEY, storage) +pub fn sequence_read(storage: &dyn Storage, emitter: &[u8]) -> u64 { + bucket_read(storage, SEQUENCE_KEY) .load(&emitter) .or::(Ok(0)) .unwrap() } -pub fn vaa_archive_add(storage: &mut S, hash: &[u8]) -> StdResult<()> { - bucket(GUARDIAN_SET_KEY, storage).save(hash, &true) +pub fn vaa_archive_add(storage: &mut dyn Storage, hash: &[u8]) -> StdResult<()> { + bucket(storage, GUARDIAN_SET_KEY).save(hash, &true) } -pub fn vaa_archive_check(storage: &S, hash: &[u8]) -> bool { - bucket_read(GUARDIAN_SET_KEY, storage) +pub fn vaa_archive_check(storage: &dyn Storage, hash: &[u8]) -> bool { + bucket_read(storage, GUARDIAN_SET_KEY) .load(&hash) .or::(Ok(false)) .unwrap() } -pub fn wrapped_asset(storage: &mut S) -> Bucket { - bucket(WRAPPED_ASSET_KEY, storage) +pub fn wrapped_asset(storage: &mut dyn Storage) -> Bucket { + bucket(storage, WRAPPED_ASSET_KEY) } -pub fn wrapped_asset_read(storage: &S) -> ReadonlyBucket { - bucket_read(WRAPPED_ASSET_KEY, storage) +pub fn wrapped_asset_read(storage: &dyn Storage) -> ReadonlyBucket { + bucket_read(storage, WRAPPED_ASSET_KEY) } -pub fn wrapped_asset_address(storage: &mut S) -> Bucket> { - bucket(WRAPPED_ASSET_ADDRESS_KEY, storage) +pub fn wrapped_asset_address(storage: &mut dyn Storage) -> Bucket> { + bucket(storage, WRAPPED_ASSET_ADDRESS_KEY) } -pub fn wrapped_asset_address_read(storage: &S) -> ReadonlyBucket> { - bucket_read(WRAPPED_ASSET_ADDRESS_KEY, storage) +pub fn wrapped_asset_address_read(storage: &dyn Storage) -> ReadonlyBucket> { + bucket_read(storage, WRAPPED_ASSET_ADDRESS_KEY) } pub struct GovernancePacket { @@ -351,7 +351,7 @@ impl SetFee { let (_, amount) = data.get_u256(0); let fee = Coin { denom: String::from(FEE_DENOMINATION), - amount: Uint128(amount), + amount: Uint128::new(amount), }; Ok(SetFee { fee }) } @@ -371,7 +371,7 @@ impl TransferFee { let (_, amount) = data.get_u256(32); let amount = Coin { denom: String::from(FEE_DENOMINATION), - amount: Uint128(amount), + amount: Uint128::new(amount), }; Ok(TransferFee { amount, recipient }) }