Преглед на файлове

terra/contracts: columbus-5 migration for wormhole

Change-Id: I6772a49d3d667633b27d74eb7f349e01c849f505
Reisen преди 4 години
родител
ревизия
c04fe95859

+ 7 - 7
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"
+serde_json = "1.0"

+ 83 - 138
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<S: Storage, A: Api, Q: Querier>(
-    deps: &mut Extern<S, A, Q>,
-    _env: Env,
-    msg: InitMsg,
-) -> StdResult<InitResponse> {
+#[cfg_attr(not(feature = "library"), entry_point)]
+pub fn instantiate(deps: DepsMut, _env: Env, msg: InstantiateMsg) -> StdResult<Response> {
     // Save general wormhole info
     let state = ConfigInfo {
         gov_chain: msg.gov_chain,
@@ -91,41 +88,39 @@ pub fn init<S: Storage, A: Api, Q: Querier>(
         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<S: Storage, A: Api, Q: Querier>(
-    deps: &mut Extern<S, A, Q>,
-    env: Env,
-    msg: HandleMsg,
-) -> StdResult<HandleResponse> {
+#[cfg_attr(not(feature = "library"), entry_point)]
+pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> StdResult<Response> {
     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<S: Storage, A: Api, Q: Querier>(
-    deps: &mut Extern<S, A, Q>,
+fn handle_submit_vaa(
+    deps: DepsMut,
     env: Env,
+    _info: MessageInfo,
     data: &[u8],
-) -> StdResult<HandleResponse> {
-    let state = config_read(&deps.storage).load()?;
+) -> StdResult<Response> {
+    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<S: Storage, A: Api, Q: Querier>(
     ContractError::InvalidVAAAction.std_err()
 }
 
-fn handle_governance_payload<S: Storage, A: Api, Q: Querier>(
-    deps: &mut Extern<S, A, Q>,
-    env: Env,
-    data: &Vec<u8>,
-) -> StdResult<HandleResponse> {
+fn handle_governance_payload(deps: DepsMut, env: Env, data: &Vec<u8>) -> StdResult<Response> {
     let gov_packet = GovernancePacket::deserialize(&data)?;
 
     let module = String::from_utf8(gov_packet.module).unwrap();
@@ -170,8 +161,8 @@ fn handle_governance_payload<S: Storage, A: Api, Q: Querier>(
 
 /// 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<S: Storage>(
-    storage: &S,
+fn parse_and_verify_vaa(
+    storage: &dyn Storage,
     data: &[u8],
     block_time: u64,
 ) -> StdResult<ParsedVAA> {
@@ -239,18 +230,14 @@ fn parse_and_verify_vaa<S: Storage>(
     Ok(vaa)
 }
 
-fn vaa_update_guardian_set<S: Storage, A: Api, Q: Querier>(
-    deps: &mut Extern<S, A, Q>,
-    env: Env,
-    data: &Vec<u8>,
-) -> StdResult<HandleResponse> {
+fn vaa_update_guardian_set(deps: DepsMut, env: Env, data: &Vec<u8>) -> StdResult<Response> {
     /* 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<S: Storage, A: Api, Q: Querier>(
 
     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<S: Storage, A: Api, Q: Querier>(
-    deps: &mut Extern<S, A, Q>,
-    env: Env,
-    data: &Vec<u8>,
-) -> StdResult<HandleResponse> {
+pub fn handle_set_fee(deps: DepsMut, _env: Env, data: &Vec<u8>) -> StdResult<Response> {
     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)?;
-
-    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,
-    })
+    config(deps.storage).save(&state)?;
+
+    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<S: Storage, A: Api, Q: Querier>(
-    deps: &mut Extern<S, A, Q>,
-    env: Env,
-    data: &Vec<u8>,
-) -> StdResult<HandleResponse> {
+pub fn handle_transfer_fee(deps: DepsMut, _env: Env, data: &Vec<u8>) -> StdResult<Response> {
     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<S: Storage, A: Api, Q: Querier>(
-    deps: &mut Extern<S, A, Q>,
+fn handle_post_message(
+    deps: DepsMut,
     env: Env,
+    info: MessageInfo,
     message: &[u8],
     nonce: u32,
-) -> StdResult<HandleResponse> {
-    let state = config_read(&deps.storage).load()?;
+) -> StdResult<Response> {
+    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 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,
-    })
+    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)?;
+
+    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<S: Storage, A: Api, Q: Querier>(
-    deps: &Extern<S, A, Q>,
-    msg: QueryMsg,
-) -> StdResult<Binary> {
+pub fn query(deps: Deps, msg: QueryMsg) -> StdResult<Binary> {
     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<S: Storage, A: Api, Q: Querier>(
     }
 }
 
-pub fn query_guardian_set_info<S: Storage, A: Api, Q: Querier>(
-    deps: &Extern<S, A, Q>,
-) -> StdResult<GuardianSetInfoResponse> {
-    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<GuardianSetInfoResponse> {
+    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<S: Storage, A: Api, Q: Querier>(
     Ok(res)
 }
 
-pub fn query_parse_and_verify_vaa<S: Storage, A: Api, Q: Querier>(
-    deps: &Extern<S, A, Q>,
+pub fn query_parse_and_verify_vaa(
+    deps: Deps,
     data: &[u8],
     block_time: u64,
 ) -> StdResult<ParsedVAA> {
-    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<S: Storage, A: Api, Q: Querier>(
-    deps: &Extern<S, A, Q>,
-    address: &HumanAddr,
-) -> StdResult<GetAddressHexResponse> {
+pub fn query_address_hex(deps: Deps, address: &HumanAddr) -> StdResult<GetAddressHexResponse> {
     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<S: Storage, A: Api, Q: Querier>(
-    deps: &Extern<S, A, Q>,
-) -> StdResult<GetStateResponse> {
-    let state = config_read(&deps.storage).load()?;
+pub fn query_state(deps: Deps) -> StdResult<GetStateResponse> {
+    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);

+ 0 - 1
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,
         }
     }
 

+ 0 - 3
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);

+ 4 - 3
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 },
 }

+ 27 - 27
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<S: Storage>(storage: &mut S) -> Singleton<S, ConfigInfo> {
+pub fn config(storage: &mut dyn Storage) -> Singleton<ConfigInfo> {
     singleton(storage, CONFIG_KEY)
 }
 
-pub fn config_read<S: Storage>(storage: &S) -> ReadonlySingleton<S, ConfigInfo> {
+pub fn config_read(storage: &dyn Storage) -> ReadonlySingleton<ConfigInfo> {
     singleton_read(storage, CONFIG_KEY)
 }
 
-pub fn guardian_set_set<S: Storage>(
-    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<S: Storage>(storage: &S, index: u32) -> StdResult<GuardianSetInfo> {
-    bucket_read(GUARDIAN_SET_KEY, storage).load(&index.to_be_bytes())
+pub fn guardian_set_get(storage: &dyn Storage, index: u32) -> StdResult<GuardianSetInfo> {
+    bucket_read(storage, GUARDIAN_SET_KEY).load(&index.to_be_bytes())
 }
 
-pub fn sequence_set<S: Storage>(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<S: Storage>(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::<u64>(Ok(0))
         .unwrap()
 }
 
-pub fn vaa_archive_add<S: Storage>(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<S: Storage>(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::<bool>(Ok(false))
         .unwrap()
 }
 
-pub fn wrapped_asset<S: Storage>(storage: &mut S) -> Bucket<S, HumanAddr> {
-    bucket(WRAPPED_ASSET_KEY, storage)
+pub fn wrapped_asset(storage: &mut dyn Storage) -> Bucket<HumanAddr> {
+    bucket(storage, WRAPPED_ASSET_KEY)
 }
 
-pub fn wrapped_asset_read<S: Storage>(storage: &S) -> ReadonlyBucket<S, HumanAddr> {
-    bucket_read(WRAPPED_ASSET_KEY, storage)
+pub fn wrapped_asset_read(storage: &dyn Storage) -> ReadonlyBucket<HumanAddr> {
+    bucket_read(storage, WRAPPED_ASSET_KEY)
 }
 
-pub fn wrapped_asset_address<S: Storage>(storage: &mut S) -> Bucket<S, Vec<u8>> {
-    bucket(WRAPPED_ASSET_ADDRESS_KEY, storage)
+pub fn wrapped_asset_address(storage: &mut dyn Storage) -> Bucket<Vec<u8>> {
+    bucket(storage, WRAPPED_ASSET_ADDRESS_KEY)
 }
 
-pub fn wrapped_asset_address_read<S: Storage>(storage: &S) -> ReadonlyBucket<S, Vec<u8>> {
-    bucket_read(WRAPPED_ASSET_ADDRESS_KEY, storage)
+pub fn wrapped_asset_address_read(storage: &dyn Storage) -> ReadonlyBucket<Vec<u8>> {
+    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 })
     }