diff --git a/contracts/cw-ics20-latest/src/contract.rs b/contracts/cw-ics20-latest/src/contract.rs index 27dc709..1e1c393 100644 --- a/contracts/cw-ics20-latest/src/contract.rs +++ b/contracts/cw-ics20-latest/src/contract.rs @@ -2,7 +2,7 @@ use cosmwasm_std::entry_point; use cosmwasm_std::{ from_binary, to_binary, Addr, Binary, Deps, DepsMut, Empty, Env, IbcEndpoint, IbcMsg, IbcQuery, - MessageInfo, Order, PortIdResponse, Response, StdError, StdResult, + MessageInfo, Order, PortIdResponse, Response, StdResult, }; use cw2::set_contract_version; use cw20::{Cw20Coin, Cw20ReceiveMsg}; @@ -21,8 +21,8 @@ use crate::msg::{ }; use crate::state::{ get_key_ics20_ibc_denom, ics20_denoms, increase_channel_balance, reduce_channel_balance, - AllowInfo, Config, MappingMetadata, RelayerFee, ADMIN, ALLOW_LIST, CHANNEL_FORWARD_STATE, - CHANNEL_INFO, CHANNEL_REVERSE_STATE, CONFIG, RELAYER_FEE, + AllowInfo, Config, MappingMetadata, TokenFee, ADMIN, ALLOW_LIST, CHANNEL_FORWARD_STATE, + CHANNEL_INFO, CHANNEL_REVERSE_STATE, CONFIG, TOKEN_FEE, }; use cw20_ics20_msg::amount::{convert_local_to_remote, Amount}; use cw_utils::{maybe_addr, nonpayable, one_coin}; @@ -39,17 +39,17 @@ pub fn instantiate( msg: InitMsg, ) -> Result { set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + let admin = deps.api.addr_validate(&msg.gov_contract)?; + ADMIN.set(deps.branch(), Some(admin.clone()))?; let cfg = Config { default_timeout: msg.default_timeout, default_gas_limit: msg.default_gas_limit, fee_denom: "orai".to_string(), swap_router_contract: msg.swap_router_contract, + fee_receiver: admin, }; CONFIG.save(deps.storage, &cfg)?; - let admin = deps.api.addr_validate(&msg.gov_contract)?; - ADMIN.set(deps.branch(), Some(admin))?; - // add all allows for allowed in msg.allowlist { let contract = deps.api.addr_validate(&allowed.contract)?; @@ -88,7 +88,8 @@ pub fn execute( fee_denom, swap_router_contract, admin, - relayer_fee, + token_fee, + fee_receiver, } => update_config( deps, info, @@ -97,7 +98,8 @@ pub fn execute( fee_denom, swap_router_contract, admin, - relayer_fee, + token_fee, + fee_receiver, ), } } @@ -110,11 +112,14 @@ pub fn update_config( fee_denom: Option, swap_router_contract: Option, admin: Option, - relayer_fee: Option, + token_fee: Option>, + fee_receiver: Option, ) -> Result { ADMIN.assert_admin(deps.as_ref(), &info.sender)?; - if let Some(relayer_fee) = relayer_fee { - RELAYER_FEE.save(deps.storage, &relayer_fee.chain, &relayer_fee.ratio)?; + if let Some(token_fee) = token_fee { + for fee in token_fee { + TOKEN_FEE.save(deps.storage, &fee.token_denom, &fee.ratio)?; + } } CONFIG.update(deps.storage, |mut config| -> StdResult { if let Some(default_timeout) = default_timeout { @@ -126,6 +131,9 @@ pub fn update_config( if let Some(swap_router_contract) = swap_router_contract { config.swap_router_contract = swap_router_contract; } + if let Some(fee_receiver) = fee_receiver { + config.fee_receiver = deps.api.addr_validate(&fee_receiver)?; + } config.default_gas_limit = default_gas_limit; Ok(config) })?; @@ -270,28 +278,27 @@ pub fn execute_transfer_back_to_remote_chain( )?; // parse denom & compare with user input. Should not use string.includes() because hacker can fake a port that has the same remote denom to return true - let mapping_search_result = mappings.into_iter().find(|pair| -> bool { - let (denom, is_native) = parse_voucher_denom( - pair.key.as_str(), - &IbcEndpoint { - port_id: parse_ibc_wasm_port_id(env.contract.address.clone().into_string()), - channel_id: msg.local_channel_id.clone(), // also verify local channel id - }, - ) - .unwrap_or_else(|_| ("", true)); // if there's an error, change is_native to true so it automatically returns false - if is_native { + let mapping = mappings + .into_iter() + .find(|pair| -> bool { + let (denom, is_native) = parse_voucher_denom( + pair.key.as_str(), + &IbcEndpoint { + port_id: parse_ibc_wasm_port_id(env.contract.address.clone().into_string()), + channel_id: msg.local_channel_id.clone(), // also verify local channel id + }, + ) + .unwrap_or_else(|_| ("", true)); // if there's an error, change is_native to true so it automatically returns false + if is_native { + return false; + } + if denom.eq(&msg.remote_denom) { + return true; + } return false; - } - if denom.eq(&msg.remote_denom) { - return true; - } - return false; - }); - if mapping_search_result.is_none() { - return Err(ContractError::MappingPairNotFound {}); - } + }) + .ok_or(ContractError::MappingPairNotFound {})?; - let mapping = mapping_search_result.unwrap(); let ibc_denom = mapping.key; // ensure the requested channel is registered if !CHANNEL_INFO.has(deps.storage, &msg.local_channel_id) { @@ -341,13 +348,8 @@ pub fn execute_transfer_back_to_remote_chain( timeout: timeout.into(), }; - let mut cosmos_msgs = collect_transfer_fee_msgs( - ADMIN - .get(deps.as_ref())? - .ok_or(StdError::generic_err("Cannot find contract admin"))? - .into_string(), - deps.storage, - )?; + let mut cosmos_msgs = + collect_transfer_fee_msgs(config.fee_receiver.into_string(), deps.storage)?; cosmos_msgs.push(msg.into()); // send response @@ -475,6 +477,7 @@ pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result StdResult { to_binary(&get_mappings_from_asset_info(deps, asset_info)?) } QueryMsg::Admin {} => to_binary(&ADMIN.query_admin(deps)?), - QueryMsg::GetTransferFee { evm_prefix } => { - to_binary(&RELAYER_FEE.load(deps.storage, &evm_prefix)?) + QueryMsg::GetTransferTokenFee { remote_token_denom } => { + to_binary(&TOKEN_FEE.load(deps.storage, &remote_token_denom)?) } } } @@ -680,8 +683,8 @@ mod test { use std::ops::Sub; use super::*; - use crate::ibc::{ibc_packet_receive, parse_asset_info_denom}; - use crate::state::{Ratio, RELAYER_FEE_ACCUMULATOR}; + use crate::ibc::ibc_packet_receive; + use crate::state::Ratio; use crate::test_helpers::*; use cosmwasm_std::testing::{mock_env, mock_info}; @@ -1121,6 +1124,7 @@ mod test { mock_env(), MigrateMsg { default_gas_limit: Some(123456), + fee_receiver: "receiver".to_string(), // default_timeout: 100u64, // fee_denom: "orai".to_string(), // swap_router_contract: "foobar".to_string(), @@ -1184,16 +1188,8 @@ mod test { let fee_amount = Uint128::from(amount) * Decimal::from_ratio(ratio.nominator, ratio.denominator); let mut deps = setup(&[remote_channel, local_channel], &[]); - RELAYER_FEE - .save(deps.as_mut().storage, "uatom", &ratio) - .unwrap(); - // reset fee so that other tests wont get affected - RELAYER_FEE_ACCUMULATOR - .save( - deps.as_mut().storage, - &parse_asset_info_denom(asset_info.clone()), - &Uint128::zero(), - ) + TOKEN_FEE + .save(deps.as_mut().storage, denom, &ratio) .unwrap(); let pair = UpdatePairMsg { @@ -1360,7 +1356,23 @@ mod test { default_gas_limit: None, fee_denom: Some("hehe".to_string()), swap_router_contract: Some("new_router".to_string()), - relayer_fee: None, + token_fee: Some(vec![ + TokenFee { + token_denom: "orai".to_string(), + ratio: Ratio { + nominator: 1, + denominator: 10, + }, + }, + TokenFee { + token_denom: "atom".to_string(), + ratio: Ratio { + nominator: 1, + denominator: 5, + }, + }, + ]), + fee_receiver: None, }; // unauthorized case let unauthorized_info = mock_info(&String::from("somebody"), &[]); @@ -1381,6 +1393,26 @@ mod test { assert_eq!(config.default_timeout, 1); assert_eq!(config.fee_denom, "hehe".to_string()); assert_eq!(config.swap_router_contract, "new_router".to_string()); + assert_eq!( + TOKEN_FEE + .range(deps.as_ref().storage, None, None, Order::Ascending) + .count(), + 2usize + ); + assert_eq!( + TOKEN_FEE + .load(deps.as_ref().storage, "orai") + .unwrap() + .denominator, + 10 + ); + assert_eq!( + TOKEN_FEE + .load(deps.as_ref().storage, "atom") + .unwrap() + .denominator, + 5 + ) } #[test] diff --git a/contracts/cw-ics20-latest/src/ibc.rs b/contracts/cw-ics20-latest/src/ibc.rs index 4349d9d..055aefd 100644 --- a/contracts/cw-ics20-latest/src/ibc.rs +++ b/contracts/cw-ics20-latest/src/ibc.rs @@ -17,8 +17,8 @@ use crate::error::{ContractError, Never}; use crate::state::{ get_key_ics20_ibc_denom, ics20_denoms, increase_channel_balance, reduce_channel_balance, undo_increase_channel_balance, undo_reduce_channel_balance, ChannelInfo, IbcSingleStepData, - MappingMetadata, Ratio, ReplyArgs, SingleStepReplyArgs, ADMIN, ALLOW_LIST, CHANNEL_INFO, - CONFIG, RELAYER_FEE, RELAYER_FEE_ACCUMULATOR, REPLY_ARGS, SINGLE_STEP_REPLY_ARGS, + MappingMetadata, Ratio, ReplyArgs, SingleStepReplyArgs, ALLOW_LIST, CHANNEL_INFO, CONFIG, + REPLY_ARGS, SINGLE_STEP_REPLY_ARGS, TOKEN_FEE, TOKEN_FEE_ACCUMULATOR, }; use cw20::{Cw20ExecuteMsg, Cw20QueryMsg, TokenInfoResponse}; use cw20_ics20_msg::amount::{convert_local_to_remote, convert_remote_to_local, Amount}; @@ -308,6 +308,19 @@ pub fn parse_voucher_denom<'a>( Ok((split_denom[2], false)) } +// Returns local denom if the denom is an encoded voucher from the expected endpoint +// Otherwise, error +pub fn parse_voucher_denom_without_sanity_checks<'a>(voucher_denom: &'a str) -> StdResult<&'a str> { + let split_denom: Vec<&str> = voucher_denom.splitn(3, '/').collect(); + + if split_denom.len() != 3 { + return Err(StdError::generic_err( + ContractError::NoForeignTokens {}.to_string(), + )); + } + Ok(split_denom[2]) +} + // this does the work of ibc_packet_receive, we wrap it to turn errors into acknowledgements fn do_ibc_packet_receive( deps: DepsMut, @@ -323,10 +336,6 @@ fn do_ibc_packet_receive( // if denom is native, we handle it the native way if denom.1 { - let admin = ADMIN - .get(deps.as_ref())? - .ok_or(StdError::generic_err("Cannot find contract admin"))? - .into_string(); return handle_ibc_packet_receive_native_remote_chain( deps.storage, deps.api, @@ -335,7 +344,6 @@ fn do_ibc_packet_receive( &denom.0, &packet, &msg, - admin, ); } @@ -377,7 +385,6 @@ fn handle_ibc_packet_receive_native_remote_chain( denom: &str, packet: &IbcPacket, msg: &Ics20Packet, - admin: String, ) -> Result { // make sure we have enough balance for this @@ -433,7 +440,8 @@ fn handle_ibc_packet_receive_native_remote_chain( .map(|msg| SubMsg::reply_on_error(msg, FOLLOW_UP_FAILURE_ID)) .collect(); - let transfer_fee_to_admin = collect_transfer_fee_msgs(admin, storage)?; + let transfer_fee_to_admin = + collect_transfer_fee_msgs(CONFIG.load(storage)?.fee_receiver.into_string(), storage)?; let mut res = IbcReceiveResponse::new() .set_ack(ack_success()) .add_messages(transfer_fee_to_admin) @@ -492,7 +500,6 @@ pub fn get_follow_up_msgs( receiver_asset_info.clone(), initial_receive_asset_info.clone(), config.fee_denom.as_str(), - &destination.destination_denom, ); let mut minimum_receive = to_send.amount(); if swap_operations.len() > 0 { @@ -562,7 +569,6 @@ pub fn build_swap_operations( receiver_asset_info: AssetInfo, initial_receive_asset_info: AssetInfo, fee_denom: &str, - destination_denom: &str, ) -> Vec { // always swap with orai first cuz its base denom & every token has a pair with it let fee_denom_asset_info = AssetInfo::NativeToken { @@ -578,7 +584,7 @@ pub fn build_swap_operations( ask_asset_info: fee_denom_asset_info.clone(), }) } - if destination_denom.ne(fee_denom) { + if receiver_asset_info.to_string().ne(fee_denom) { swap_operations.push(SwapOperation::OraiSwap { offer_asset_info: fee_denom_asset_info.clone(), ask_asset_info: receiver_asset_info, @@ -663,13 +669,6 @@ pub fn build_ibc_msg( }; let (is_evm_based, destination) = destination.is_receiver_evm_based(); if is_evm_based { - // also deduct fee here because of round trip - let new_deducted_amount = process_deduct_fee( - storage, - &destination.destination_denom, - amount, - &parse_asset_info_denom(receiver_asset_info.clone()), - )?; // use sender from ICS20Packet as receiver when transferring back let pair_mappings: Vec<(String, MappingMetadata)> = ics20_denoms() .idx @@ -682,6 +681,13 @@ pub fn build_ibc_msg( .into_iter() .find(|(key, _)| key.contains(&destination.destination_channel)) .ok_or(StdError::generic_err("cannot find pair mappings"))?; + // also deduct fee here because of round trip + let new_deducted_amount = process_deduct_fee( + storage, + parse_voucher_denom_without_sanity_checks(&mapping.0)?, + amount, + &parse_asset_info_denom(receiver_asset_info.clone()), + )?; let remote_amount = convert_local_to_remote( new_deducted_amount, mapping.1.remote_decimals, @@ -797,11 +803,10 @@ pub fn process_deduct_fee( amount: Uint128, local_token_denom: &str, ) -> StdResult { - let evm_prefix = convert_remote_denom_to_evm_prefix(remote_token_denom); - let relayer_fee = RELAYER_FEE.may_load(storage, &evm_prefix)?; - if let Some(relayer_fee) = relayer_fee { - let fee = deduct_fee(relayer_fee, amount); - RELAYER_FEE_ACCUMULATOR.update( + let token_fee = TOKEN_FEE.may_load(storage, &remote_token_denom)?; + if let Some(token_fee) = token_fee { + let fee = deduct_fee(token_fee, amount); + TOKEN_FEE_ACCUMULATOR.update( storage, local_token_denom, |prev_fee| -> StdResult { Ok(prev_fee.unwrap_or_default().checked_add(fee)?) }, @@ -812,29 +817,29 @@ pub fn process_deduct_fee( Ok(amount) } -pub fn deduct_fee(relayer_fee: Ratio, amount: Uint128) -> Uint128 { +pub fn deduct_fee(token_fee: Ratio, amount: Uint128) -> Uint128 { // ignore case where denominator is zero since we cannot divide with 0 - if relayer_fee.denominator == 0 { + if token_fee.denominator == 0 { return Uint128::from(0u64); } amount.mul(Decimal::from_ratio( - relayer_fee.nominator, - relayer_fee.denominator, + token_fee.nominator, + token_fee.denominator, )) } -pub fn convert_remote_denom_to_evm_prefix(remote_denom: &str) -> String { - match remote_denom.split_once("0x") { - Some((evm_prefix, _)) => return evm_prefix.to_string(), - None => "".to_string(), - } -} +// pub fn convert_remote_denom_to_evm_prefix(remote_denom: &str) -> String { +// match remote_denom.split_once("0x") { +// Some((evm_prefix, _)) => return evm_prefix.to_string(), +// None => "".to_string(), +// } +// } pub fn collect_transfer_fee_msgs( - admin: String, + receiver: String, storage: &mut dyn Storage, ) -> StdResult> { - let cosmos_msgs = RELAYER_FEE_ACCUMULATOR + let cosmos_msgs = TOKEN_FEE_ACCUMULATOR .range(storage, None, None, Order::Ascending) .filter(|data| { if let Some(filter_result) = data @@ -853,21 +858,20 @@ pub fn collect_transfer_fee_msgs( }) .map(|data| { data.map(|fee_info| { - println!("fee info: {}", fee_info.1); send_amount( Amount::from_parts(fee_info.0, fee_info.1), - admin.clone(), + receiver.clone(), None, ) }) }) .collect::>>(); // we reset all the accumulator keys to zero so that it wont accumulate more in the next txs. This action will be reverted if the fee payment txs fail. - RELAYER_FEE_ACCUMULATOR + TOKEN_FEE_ACCUMULATOR .keys(storage, None, None, Order::Ascending) .collect::, StdError>>()? .into_iter() - .for_each(|key| RELAYER_FEE_ACCUMULATOR.remove(storage, &key)); + .for_each(|key| TOKEN_FEE_ACCUMULATOR.remove(storage, &key)); cosmos_msgs } diff --git a/contracts/cw-ics20-latest/src/ibc_tests.rs b/contracts/cw-ics20-latest/src/ibc_tests.rs index 8126988..4d002c6 100644 --- a/contracts/cw-ics20-latest/src/ibc_tests.rs +++ b/contracts/cw-ics20-latest/src/ibc_tests.rs @@ -6,10 +6,10 @@ mod test { use oraiswap::router::SwapOperation; use crate::ibc::{ - ack_fail, build_ibc_msg, build_swap_msgs, check_gas_limit, - convert_remote_denom_to_evm_prefix, deduct_fee, handle_follow_up_failure, - ibc_packet_receive, is_follow_up_msgs_only_send_amount, parse_voucher_denom, - process_deduct_fee, send_amount, Ics20Ack, Ics20Packet, RECEIVE_ID, REFUND_FAILURE_ID, + ack_fail, build_ibc_msg, build_swap_msgs, check_gas_limit, deduct_fee, + handle_follow_up_failure, ibc_packet_receive, is_follow_up_msgs_only_send_amount, + parse_voucher_denom, parse_voucher_denom_without_sanity_checks, process_deduct_fee, + send_amount, Ics20Ack, Ics20Packet, RECEIVE_ID, REFUND_FAILURE_ID, }; use crate::ibc::{build_swap_operations, get_follow_up_msgs}; use crate::test_helpers::*; @@ -21,8 +21,8 @@ mod test { use crate::error::ContractError; use crate::state::{ get_key_ics20_ibc_denom, increase_channel_balance, ChannelState, IbcSingleStepData, Ratio, - SingleStepReplyArgs, CHANNEL_REVERSE_STATE, RELAYER_FEE, RELAYER_FEE_ACCUMULATOR, - SINGLE_STEP_REPLY_ARGS, + SingleStepReplyArgs, CHANNEL_REVERSE_STATE, SINGLE_STEP_REPLY_ARGS, TOKEN_FEE, + TOKEN_FEE_ACCUMULATOR, }; use cw20::{Cw20Coin, Cw20ExecuteMsg}; use cw20_ics20_msg::amount::{convert_local_to_remote, Amount}; @@ -317,6 +317,7 @@ mod test { mock_env(), MigrateMsg { default_gas_limit: Some(def_limit), + fee_receiver: "receiver".to_string(), // default_timeout: 100u64, // fee_denom: "orai".to_string(), // swap_router_contract: "foobar".to_string(), @@ -342,7 +343,7 @@ mod test { ) -> IbcPacket { let data = Ics20Packet { // this is returning a foreign native token, thus denom is , eg: uatom - denom: format!("{}", denom), + denom: denom.to_string(), amount: amount.into(), sender: "remote-sender".to_string(), receiver: receiver.to_string(), @@ -465,10 +466,10 @@ mod test { &["channel-1", "channel-7", send_channel], &[(cw20_addr, gas_limit)], ); - RELAYER_FEE + TOKEN_FEE .save( deps.as_mut().storage, - "uatom", + denom, &Ratio { nominator: 1, denominator: 10, @@ -554,26 +555,19 @@ mod test { contract_addr: Addr::unchecked("addr"), }; let fee_denom = "orai".to_string(); - let mut destination: DestinationInfo = DestinationInfo { - receiver: "cosmos".to_string(), - destination_channel: "channel-1".to_string(), - destination_denom: "foobar".to_string(), - }; let operations = build_swap_operations( receiver_asset_info.clone(), initial_asset_info.clone(), fee_denom.as_str(), - &destination.destination_denom, ); assert_eq!(operations.len(), 2); - let fee_denom = "foobar".to_string(); + let fee_denom = "contract".to_string(); let operations = build_swap_operations( receiver_asset_info.clone(), initial_asset_info.clone(), &fee_denom, - &destination.destination_denom, ); assert_eq!(operations.len(), 1); assert_eq!( @@ -586,31 +580,29 @@ mod test { } ); initial_asset_info = AssetInfo::NativeToken { - denom: "foobar".to_string(), + denom: "contract".to_string(), }; let operations = build_swap_operations( receiver_asset_info.clone(), initial_asset_info.clone(), &fee_denom, - &destination.destination_denom, ); assert_eq!(operations.len(), 0); - destination.destination_denom = "atom".to_string(); + initial_asset_info = AssetInfo::Token { + contract_addr: Addr::unchecked("addr"), + }; let operations = build_swap_operations( receiver_asset_info.clone(), initial_asset_info.clone(), &fee_denom, - &destination.destination_denom, ); assert_eq!(operations.len(), 1); assert_eq!( operations[0], SwapOperation::OraiSwap { - offer_asset_info: AssetInfo::NativeToken { - denom: fee_denom.clone() - }, - ask_asset_info: receiver_asset_info.clone() + offer_asset_info: initial_asset_info.clone(), + ask_asset_info: AssetInfo::NativeToken { denom: fee_denom } } ); @@ -619,9 +611,10 @@ mod test { AssetInfo::NativeToken { denom: "foobar".to_string(), }, - initial_asset_info.clone(), + AssetInfo::NativeToken { + denom: "foobar".to_string(), + }, "not_foo_bar", - &destination.destination_denom, ); assert_eq!(operations.len(), 0); } @@ -1085,14 +1078,28 @@ mod test { ); } + // #[test] + // fn test_convert_remote_denom_to_evm_prefix() { + // assert_eq!(convert_remote_denom_to_evm_prefix("abcd"), "".to_string()); + // assert_eq!(convert_remote_denom_to_evm_prefix("0x"), "".to_string()); + // assert_eq!( + // convert_remote_denom_to_evm_prefix("evm0x"), + // "evm".to_string() + // ); + // } + #[test] - fn test_convert_remote_denom_to_evm_prefix() { - assert_eq!(convert_remote_denom_to_evm_prefix("abcd"), "".to_string()); - assert_eq!(convert_remote_denom_to_evm_prefix("0x"), "".to_string()); + fn test_parse_voucher_denom_without_sanity_checks() { + assert_eq!( + parse_voucher_denom_without_sanity_checks("foo").is_err(), + true + ); assert_eq!( - convert_remote_denom_to_evm_prefix("evm0x"), - "evm".to_string() + parse_voucher_denom_without_sanity_checks("foo/bar").is_err(), + true ); + let result = parse_voucher_denom_without_sanity_checks("foo/bar/helloworld").unwrap(); + assert_eq!(result, "helloworld"); } #[test] @@ -1100,15 +1107,16 @@ mod test { let mut deps = mock_dependencies(); let amount = Uint128::from(1000u64); let storage = deps.as_mut().storage; + let token_fee_denom = "foo0x"; // should return amount because we have not set relayer fee yet assert_eq!( process_deduct_fee(storage, "foo", amount, "foo").unwrap(), amount.clone() ); - RELAYER_FEE + TOKEN_FEE .save( storage, - "foo", + token_fee_denom, &Ratio { nominator: 1, denominator: 100, @@ -1116,11 +1124,11 @@ mod test { ) .unwrap(); assert_eq!( - process_deduct_fee(storage, "foo0x", amount, "foo").unwrap(), + process_deduct_fee(storage, token_fee_denom, amount, "foo").unwrap(), Uint128::from(990u64) ); assert_eq!( - RELAYER_FEE_ACCUMULATOR.load(storage, "foo").unwrap(), + TOKEN_FEE_ACCUMULATOR.load(storage, "foo").unwrap(), Uint128::from(10u64) ); } diff --git a/contracts/cw-ics20-latest/src/msg.rs b/contracts/cw-ics20-latest/src/msg.rs index aa83895..0201098 100644 --- a/contracts/cw-ics20-latest/src/msg.rs +++ b/contracts/cw-ics20-latest/src/msg.rs @@ -3,7 +3,7 @@ use cosmwasm_std::{Binary, IbcEndpoint}; use cw20::Cw20ReceiveMsg; use oraiswap::asset::AssetInfo; -use crate::state::{ChannelInfo, MappingMetadata, Ratio, RelayerFee}; +use crate::state::{ChannelInfo, MappingMetadata, Ratio, TokenFee}; use cw20_ics20_msg::amount::Amount; #[cw_serde] @@ -31,6 +31,7 @@ pub struct AllowMsg { pub struct MigrateMsg { // pub default_timeout: u64, pub default_gas_limit: Option, + pub fee_receiver: String, // pub fee_denom: String, // pub swap_router_contract: String, } @@ -53,7 +54,8 @@ pub enum ExecuteMsg { default_gas_limit: Option, fee_denom: Option, swap_router_contract: Option, - relayer_fee: Option, + token_fee: Option>, + fee_receiver: Option, }, } @@ -157,7 +159,7 @@ pub enum QueryMsg { #[returns(Vec)] PairMappingsFromAssetInfo { asset_info: AssetInfo }, #[returns(Ratio)] - GetTransferFee { evm_prefix: String }, + GetTransferTokenFee { remote_token_denom: String }, } #[cw_serde] diff --git a/contracts/cw-ics20-latest/src/state.rs b/contracts/cw-ics20-latest/src/state.rs index d002ab4..ffc67ce 100644 --- a/contracts/cw-ics20-latest/src/state.rs +++ b/contracts/cw-ics20-latest/src/state.rs @@ -29,9 +29,9 @@ pub const CHANNEL_REVERSE_STATE: Map<(&str, &str), ChannelState> = /// Every cw20 contract we allow to be sent is stored here, possibly with a gas_limit pub const ALLOW_LIST: Map<&Addr, AllowInfo> = Map::new("allow_list"); -pub const RELAYER_FEE: Map<&str, Ratio> = Map::new("relayer_fee"); +pub const TOKEN_FEE: Map<&str, Ratio> = Map::new("token_fee"); -pub const RELAYER_FEE_ACCUMULATOR: Map<&str, Uint128> = Map::new("fee_accumulator"); +pub const TOKEN_FEE_ACCUMULATOR: Map<&str, Uint128> = Map::new("token_fee_accumulator"); // MappingMetadataIndexex structs keeps a list of indexers pub struct MappingMetadataIndexex<'a> { @@ -72,6 +72,7 @@ pub struct Config { pub default_gas_limit: Option, pub fee_denom: String, pub swap_router_contract: String, + pub fee_receiver: Addr, } #[cw_serde] @@ -90,8 +91,8 @@ pub struct AllowInfo { } #[cw_serde] -pub struct RelayerFee { - pub chain: String, +pub struct TokenFee { + pub token_denom: String, pub ratio: Ratio, }