2
2
use cosmwasm_std:: entry_point;
3
3
use cosmwasm_std:: {
4
4
from_binary, to_binary, Addr , Binary , Deps , DepsMut , Empty , Env , IbcEndpoint , IbcMsg , IbcQuery ,
5
- MessageInfo , Order , PortIdResponse , Response , StdError , StdResult ,
5
+ MessageInfo , Order , PortIdResponse , Response , StdResult ,
6
6
} ;
7
7
use cw2:: set_contract_version;
8
8
use cw20:: { Cw20Coin , Cw20ReceiveMsg } ;
@@ -21,8 +21,8 @@ use crate::msg::{
21
21
} ;
22
22
use crate :: state:: {
23
23
get_key_ics20_ibc_denom, ics20_denoms, increase_channel_balance, reduce_channel_balance,
24
- AllowInfo , Config , MappingMetadata , RelayerFee , ADMIN , ALLOW_LIST , CHANNEL_FORWARD_STATE ,
25
- CHANNEL_INFO , CHANNEL_REVERSE_STATE , CONFIG , RELAYER_FEE ,
24
+ AllowInfo , Config , MappingMetadata , TokenFee , ADMIN , ALLOW_LIST , CHANNEL_FORWARD_STATE ,
25
+ CHANNEL_INFO , CHANNEL_REVERSE_STATE , CONFIG , TOKEN_FEE ,
26
26
} ;
27
27
use cw20_ics20_msg:: amount:: { convert_local_to_remote, Amount } ;
28
28
use cw_utils:: { maybe_addr, nonpayable, one_coin} ;
@@ -39,17 +39,17 @@ pub fn instantiate(
39
39
msg : InitMsg ,
40
40
) -> Result < Response , ContractError > {
41
41
set_contract_version ( deps. storage , CONTRACT_NAME , CONTRACT_VERSION ) ?;
42
+ let admin = deps. api . addr_validate ( & msg. gov_contract ) ?;
43
+ ADMIN . set ( deps. branch ( ) , Some ( admin. clone ( ) ) ) ?;
42
44
let cfg = Config {
43
45
default_timeout : msg. default_timeout ,
44
46
default_gas_limit : msg. default_gas_limit ,
45
47
fee_denom : "orai" . to_string ( ) ,
46
48
swap_router_contract : msg. swap_router_contract ,
49
+ fee_receiver : admin,
47
50
} ;
48
51
CONFIG . save ( deps. storage , & cfg) ?;
49
52
50
- let admin = deps. api . addr_validate ( & msg. gov_contract ) ?;
51
- ADMIN . set ( deps. branch ( ) , Some ( admin) ) ?;
52
-
53
53
// add all allows
54
54
for allowed in msg. allowlist {
55
55
let contract = deps. api . addr_validate ( & allowed. contract ) ?;
@@ -88,7 +88,8 @@ pub fn execute(
88
88
fee_denom,
89
89
swap_router_contract,
90
90
admin,
91
- relayer_fee,
91
+ token_fee,
92
+ fee_receiver,
92
93
} => update_config (
93
94
deps,
94
95
info,
@@ -97,7 +98,8 @@ pub fn execute(
97
98
fee_denom,
98
99
swap_router_contract,
99
100
admin,
100
- relayer_fee,
101
+ token_fee,
102
+ fee_receiver,
101
103
) ,
102
104
}
103
105
}
@@ -110,11 +112,14 @@ pub fn update_config(
110
112
fee_denom : Option < String > ,
111
113
swap_router_contract : Option < String > ,
112
114
admin : Option < String > ,
113
- relayer_fee : Option < RelayerFee > ,
115
+ token_fee : Option < Vec < TokenFee > > ,
116
+ fee_receiver : Option < String > ,
114
117
) -> Result < Response , ContractError > {
115
118
ADMIN . assert_admin ( deps. as_ref ( ) , & info. sender ) ?;
116
- if let Some ( relayer_fee) = relayer_fee {
117
- RELAYER_FEE . save ( deps. storage , & relayer_fee. chain , & relayer_fee. ratio ) ?;
119
+ if let Some ( token_fee) = token_fee {
120
+ for fee in token_fee {
121
+ TOKEN_FEE . save ( deps. storage , & fee. token_denom , & fee. ratio ) ?;
122
+ }
118
123
}
119
124
CONFIG . update ( deps. storage , |mut config| -> StdResult < Config > {
120
125
if let Some ( default_timeout) = default_timeout {
@@ -126,6 +131,9 @@ pub fn update_config(
126
131
if let Some ( swap_router_contract) = swap_router_contract {
127
132
config. swap_router_contract = swap_router_contract;
128
133
}
134
+ if let Some ( fee_receiver) = fee_receiver {
135
+ config. fee_receiver = deps. api . addr_validate ( & fee_receiver) ?;
136
+ }
129
137
config. default_gas_limit = default_gas_limit;
130
138
Ok ( config)
131
139
} ) ?;
@@ -270,28 +278,27 @@ pub fn execute_transfer_back_to_remote_chain(
270
278
) ?;
271
279
272
280
// 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
273
- let mapping_search_result = mappings. into_iter ( ) . find ( |pair| -> bool {
274
- let ( denom, is_native) = parse_voucher_denom (
275
- pair. key . as_str ( ) ,
276
- & IbcEndpoint {
277
- port_id : parse_ibc_wasm_port_id ( env. contract . address . clone ( ) . into_string ( ) ) ,
278
- channel_id : msg. local_channel_id . clone ( ) , // also verify local channel id
279
- } ,
280
- )
281
- . unwrap_or_else ( |_| ( "" , true ) ) ; // if there's an error, change is_native to true so it automatically returns false
282
- if is_native {
281
+ let mapping = mappings
282
+ . into_iter ( )
283
+ . find ( |pair| -> bool {
284
+ let ( denom, is_native) = parse_voucher_denom (
285
+ pair. key . as_str ( ) ,
286
+ & IbcEndpoint {
287
+ port_id : parse_ibc_wasm_port_id ( env. contract . address . clone ( ) . into_string ( ) ) ,
288
+ channel_id : msg. local_channel_id . clone ( ) , // also verify local channel id
289
+ } ,
290
+ )
291
+ . unwrap_or_else ( |_| ( "" , true ) ) ; // if there's an error, change is_native to true so it automatically returns false
292
+ if is_native {
293
+ return false ;
294
+ }
295
+ if denom. eq ( & msg. remote_denom ) {
296
+ return true ;
297
+ }
283
298
return false ;
284
- }
285
- if denom. eq ( & msg. remote_denom ) {
286
- return true ;
287
- }
288
- return false ;
289
- } ) ;
290
- if mapping_search_result. is_none ( ) {
291
- return Err ( ContractError :: MappingPairNotFound { } ) ;
292
- }
299
+ } )
300
+ . ok_or ( ContractError :: MappingPairNotFound { } ) ?;
293
301
294
- let mapping = mapping_search_result. unwrap ( ) ;
295
302
let ibc_denom = mapping. key ;
296
303
// ensure the requested channel is registered
297
304
if !CHANNEL_INFO . has ( deps. storage , & msg. local_channel_id ) {
@@ -341,13 +348,8 @@ pub fn execute_transfer_back_to_remote_chain(
341
348
timeout : timeout. into ( ) ,
342
349
} ;
343
350
344
- let mut cosmos_msgs = collect_transfer_fee_msgs (
345
- ADMIN
346
- . get ( deps. as_ref ( ) ) ?
347
- . ok_or ( StdError :: generic_err ( "Cannot find contract admin" ) ) ?
348
- . into_string ( ) ,
349
- deps. storage ,
350
- ) ?;
351
+ let mut cosmos_msgs =
352
+ collect_transfer_fee_msgs ( config. fee_receiver . into_string ( ) , deps. storage ) ?;
351
353
cosmos_msgs. push ( msg. into ( ) ) ;
352
354
353
355
// send response
@@ -475,6 +477,7 @@ pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result<Response, Co
475
477
default_gas_limit : msg. default_gas_limit ,
476
478
fee_denom : config. fee_denom ,
477
479
swap_router_contract : config. swap_router_contract ,
480
+ fee_receiver : deps. api . addr_validate ( & msg. fee_receiver ) ?,
478
481
} ,
479
482
) ?;
480
483
set_contract_version ( deps. storage , CONTRACT_NAME , CONTRACT_VERSION ) ?;
@@ -504,8 +507,8 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
504
507
to_binary ( & get_mappings_from_asset_info ( deps, asset_info) ?)
505
508
}
506
509
QueryMsg :: Admin { } => to_binary ( & ADMIN . query_admin ( deps) ?) ,
507
- QueryMsg :: GetTransferFee { evm_prefix } => {
508
- to_binary ( & RELAYER_FEE . load ( deps. storage , & evm_prefix ) ?)
510
+ QueryMsg :: GetTransferTokenFee { remote_token_denom } => {
511
+ to_binary ( & TOKEN_FEE . load ( deps. storage , & remote_token_denom ) ?)
509
512
}
510
513
}
511
514
}
@@ -680,8 +683,8 @@ mod test {
680
683
use std:: ops:: Sub ;
681
684
682
685
use super :: * ;
683
- use crate :: ibc:: { ibc_packet_receive, parse_asset_info_denom } ;
684
- use crate :: state:: { Ratio , RELAYER_FEE_ACCUMULATOR } ;
686
+ use crate :: ibc:: ibc_packet_receive;
687
+ use crate :: state:: Ratio ;
685
688
use crate :: test_helpers:: * ;
686
689
687
690
use cosmwasm_std:: testing:: { mock_env, mock_info} ;
@@ -1121,6 +1124,7 @@ mod test {
1121
1124
mock_env ( ) ,
1122
1125
MigrateMsg {
1123
1126
default_gas_limit : Some ( 123456 ) ,
1127
+ fee_receiver : "receiver" . to_string ( ) ,
1124
1128
// default_timeout: 100u64,
1125
1129
// fee_denom: "orai".to_string(),
1126
1130
// swap_router_contract: "foobar".to_string(),
@@ -1184,16 +1188,8 @@ mod test {
1184
1188
let fee_amount =
1185
1189
Uint128 :: from ( amount) * Decimal :: from_ratio ( ratio. nominator , ratio. denominator ) ;
1186
1190
let mut deps = setup ( & [ remote_channel, local_channel] , & [ ] ) ;
1187
- RELAYER_FEE
1188
- . save ( deps. as_mut ( ) . storage , "uatom" , & ratio)
1189
- . unwrap ( ) ;
1190
- // reset fee so that other tests wont get affected
1191
- RELAYER_FEE_ACCUMULATOR
1192
- . save (
1193
- deps. as_mut ( ) . storage ,
1194
- & parse_asset_info_denom ( asset_info. clone ( ) ) ,
1195
- & Uint128 :: zero ( ) ,
1196
- )
1191
+ TOKEN_FEE
1192
+ . save ( deps. as_mut ( ) . storage , denom, & ratio)
1197
1193
. unwrap ( ) ;
1198
1194
1199
1195
let pair = UpdatePairMsg {
@@ -1360,7 +1356,23 @@ mod test {
1360
1356
default_gas_limit : None ,
1361
1357
fee_denom : Some ( "hehe" . to_string ( ) ) ,
1362
1358
swap_router_contract : Some ( "new_router" . to_string ( ) ) ,
1363
- relayer_fee : None ,
1359
+ token_fee : Some ( vec ! [
1360
+ TokenFee {
1361
+ token_denom: "orai" . to_string( ) ,
1362
+ ratio: Ratio {
1363
+ nominator: 1 ,
1364
+ denominator: 10 ,
1365
+ } ,
1366
+ } ,
1367
+ TokenFee {
1368
+ token_denom: "atom" . to_string( ) ,
1369
+ ratio: Ratio {
1370
+ nominator: 1 ,
1371
+ denominator: 5 ,
1372
+ } ,
1373
+ } ,
1374
+ ] ) ,
1375
+ fee_receiver : None ,
1364
1376
} ;
1365
1377
// unauthorized case
1366
1378
let unauthorized_info = mock_info ( & String :: from ( "somebody" ) , & [ ] ) ;
@@ -1381,6 +1393,26 @@ mod test {
1381
1393
assert_eq ! ( config. default_timeout, 1 ) ;
1382
1394
assert_eq ! ( config. fee_denom, "hehe" . to_string( ) ) ;
1383
1395
assert_eq ! ( config. swap_router_contract, "new_router" . to_string( ) ) ;
1396
+ assert_eq ! (
1397
+ TOKEN_FEE
1398
+ . range( deps. as_ref( ) . storage, None , None , Order :: Ascending )
1399
+ . count( ) ,
1400
+ 2usize
1401
+ ) ;
1402
+ assert_eq ! (
1403
+ TOKEN_FEE
1404
+ . load( deps. as_ref( ) . storage, "orai" )
1405
+ . unwrap( )
1406
+ . denominator,
1407
+ 10
1408
+ ) ;
1409
+ assert_eq ! (
1410
+ TOKEN_FEE
1411
+ . load( deps. as_ref( ) . storage, "atom" )
1412
+ . unwrap( )
1413
+ . denominator,
1414
+ 5
1415
+ )
1384
1416
}
1385
1417
1386
1418
#[ test]
0 commit comments