From a0559034213b52d62087ff0049ef4c8694b8349d Mon Sep 17 00:00:00 2001 From: "M. Daeva" Date: Sun, 17 Sep 2023 18:44:18 +0300 Subject: [PATCH] updated IBC verification --- Cargo.lock | 9 +- Cargo.toml | 1 + config/kujira-testnet-config.json | 4 +- config/osmosis-testnet-config.json | 8 +- .../eldorado-aggregator-kujira/Cargo.toml | 2 +- .../schema/eldorado-aggregator-kujira.json | 8 +- .../src/actions/execute.rs | 128 +++++++++++------- .../src/actions/instantiate.rs | 7 +- .../src/actions/other.rs | 1 + .../eldorado-aggregator-kujira/testnet.sh | 79 ++++++----- .../src/actions/execute.rs | 102 +++++++------- .../src/actions/other.rs | 50 +++---- .../src/actions/query.rs | 29 +++- .../eldorado-aggregator-osmosis/testnet.sh | 61 +++++---- packages/eldorado-base/Cargo.toml | 3 +- packages/eldorado-base/src/converters.rs | 11 +- .../src/eldorado_aggregator_kujira/state.rs | 8 +- .../src/eldorado_aggregator_osmosis/state.rs | 3 +- packages/eldorado-base/src/error.rs | 11 +- packages/eldorado-base/src/types.rs | 1 + tests/src/eldorado_aggregator_kujira.rs | 11 +- tests/src/helpers/suite/core.rs | 6 + 22 files changed, 322 insertions(+), 221 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1778504..c9280f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,6 +49,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "block-buffer" version = "0.9.0" @@ -407,7 +413,7 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "eldorado-aggregator-kujira" -version = "1.0.0" +version = "1.1.0" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -437,6 +443,7 @@ dependencies = [ name = "eldorado-base" version = "1.0.0" dependencies = [ + "bech32", "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus", diff --git a/Cargo.toml b/Cargo.toml index 1d95c17..597d7c5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ cw-multi-test = "0.16.5" speculoos = "0.11.0" kujira = { git = "https://github.com/Team-Kujira/kujira-rs" } osmosis-std = "0.19.1" +bech32 = "0.9.1" eldorado-base = { path = "./packages/eldorado-base" } mantaswap-mocks = { path = "./packages/mantaswap-mocks" } diff --git a/config/kujira-testnet-config.json b/config/kujira-testnet-config.json index 19d3bde..ac48c78 100644 --- a/config/kujira-testnet-config.json +++ b/config/kujira-testnet-config.json @@ -2,6 +2,6 @@ "PREFIX": "kujira", "CHAIN_ID": "harpoon-4", "RPC": "https://kujira-testnet-rpc.polkachu.com:443", - "CONTRACT_CODE": "2422", - "CONTRACT_ADDRESS": "kujira1mmhrcaxwe6qtcpnd7ua46qywwyndhpcfzrn8atyslfcwttjwkrcsq0v6f7" + "CONTRACT_CODE": "2448", + "CONTRACT_ADDRESS": "kujira1wlkn8px6y5jfp9suqusdjmnhysd4594qsju87694gl5mlckjwscs87sfdg" } \ No newline at end of file diff --git a/config/osmosis-testnet-config.json b/config/osmosis-testnet-config.json index fe066ae..1137d65 100644 --- a/config/osmosis-testnet-config.json +++ b/config/osmosis-testnet-config.json @@ -1 +1,7 @@ -{ "PREFIX":"osmo", "CHAIN_ID":"osmo-test-5", "RPC":"https://rpc.osmotest5.osmosis.zone:443", "CONTRACT_CODE":"4257", "CONTRACT_ADDRESS":"osmo1n9qe5jjq3w3mc4pgz7jswknrluq6dwzdw2hzc8apddqw4k0p2ulqg5xxee" } +{ + "PREFIX": "osmo", + "CHAIN_ID": "osmo-test-5", + "RPC": "https://rpc.osmotest5.osmosis.zone:443", + "CONTRACT_CODE": "4288", + "CONTRACT_ADDRESS": "osmo1pmhdtae4zyvjveva9f6a9tgenslyr46w5ws67u7447473cn9gqxqhl92d7" +} \ No newline at end of file diff --git a/contracts/eldorado-aggregator-kujira/Cargo.toml b/contracts/eldorado-aggregator-kujira/Cargo.toml index 034aad2..0afd9cc 100644 --- a/contracts/eldorado-aggregator-kujira/Cargo.toml +++ b/contracts/eldorado-aggregator-kujira/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "eldorado-aggregator-kujira" -version = "1.0.0" +version = "1.1.0" authors = ["M. Daeva "] edition = "2021" diff --git a/contracts/eldorado-aggregator-kujira/schema/eldorado-aggregator-kujira.json b/contracts/eldorado-aggregator-kujira/schema/eldorado-aggregator-kujira.json index 700e088..28ee138 100644 --- a/contracts/eldorado-aggregator-kujira/schema/eldorado-aggregator-kujira.json +++ b/contracts/eldorado-aggregator-kujira/schema/eldorado-aggregator-kujira.json @@ -1,6 +1,6 @@ { "contract_name": "eldorado-aggregator-kujira", - "contract_version": "1.0.0", + "contract_version": "1.1.0", "idl_version": "1.0.0", "instantiate": { "$schema": "http://json-schema.org/draft-07/schema#", @@ -47,7 +47,7 @@ "additionalProperties": false }, { - "description": "Called by vault to: 1) swap native Kuji -> token on Kujira (or don't swap if Kuji is asked asset) 2) send token on Kujira to user address on Kujira or other Cosmos network", + "description": "Called by vault to: 1) swap native Kuji -> token on Kujira 2) send token on Kujira to user address on Kujira or other Cosmos network", "type": "object", "required": [ "swap_out" @@ -272,6 +272,7 @@ "type": "object", "required": [ "admin", + "chain_id", "ibc_timeout", "router" ], @@ -279,6 +280,9 @@ "admin": { "$ref": "#/definitions/Addr" }, + "chain_id": { + "type": "string" + }, "ibc_timeout": { "type": "integer", "format": "uint64", diff --git a/contracts/eldorado-aggregator-kujira/src/actions/execute.rs b/contracts/eldorado-aggregator-kujira/src/actions/execute.rs index dddcded..85abfa3 100644 --- a/contracts/eldorado-aggregator-kujira/src/actions/execute.rs +++ b/contracts/eldorado-aggregator-kujira/src/actions/execute.rs @@ -1,12 +1,14 @@ use cosmwasm_std::{ - to_binary, Coin, CosmosMsg, Deps, DepsMut, Env, MessageInfo, Response, SubMsg, WasmMsg, + to_binary, Addr, Coin, CosmosMsg, Deps, DepsMut, Env, MessageInfo, Response, SubMsg, WasmMsg, }; use cw_utils::{must_pay, nonpayable, one_coin}; use eldorado_base::{ + converters::get_addr_by_prefix, eldorado_aggregator_kujira::state::{ - Config, CONFIG, DENOM_KUJI, RECIPIENT_PARAMETERS, SWAP_IN_REPLY, SWAP_OUT_REPLY, + Config, BASE_DENOM, BASE_PREFIX, CHAIN_ID_DEV, CONFIG, RECIPIENT_PARAMETERS, SWAP_IN_REPLY, + SWAP_OUT_REPLY, }, error::ContractError, mantaswap, @@ -22,25 +24,15 @@ pub fn try_swap_in( ) -> Result { let coin = one_coin(&info).map_err(|e| ContractError::CustomError { val: e.to_string() })?; let wasm_msg = get_wasm_msg( - &deps.as_ref(), - env.contract.address.as_str(), + deps, + &env, + &vault_address, &mantaswap_msg, &vec![coin], + &None, )?; let submsg = SubMsg::reply_on_success(CosmosMsg::Wasm(wasm_msg), SWAP_IN_REPLY); - RECIPIENT_PARAMETERS.update( - deps.storage, - |mut x| -> Result, ContractError> { - x.push(RecipientParameters { - recipient_address: deps.api.addr_validate(&vault_address)?, - channel_id: None, - }); - - Ok(x) - }, - )?; - Ok(Response::new() .add_submessage(submsg) .add_attributes([("action", "try_swap_in")])) @@ -54,34 +46,22 @@ pub fn try_swap_out( mantaswap_msg: mantaswap::msg::ExecuteMsg, channel_id: Option, ) -> Result { - verify_ibc_parameters(&mantaswap_msg, &channel_id)?; - - let amount = must_pay(&info, DENOM_KUJI) + let amount = must_pay(&info, BASE_DENOM) .map_err(|e| ContractError::CustomError { val: e.to_string() })?; let coin = Coin { - denom: DENOM_KUJI.to_string(), + denom: BASE_DENOM.to_string(), amount, }; let wasm_msg = get_wasm_msg( - &deps.as_ref(), - env.contract.address.as_str(), + deps, + &env, + &user_address, &mantaswap_msg, &vec![coin], + &channel_id, )?; let submsg = SubMsg::reply_on_success(CosmosMsg::Wasm(wasm_msg), SWAP_OUT_REPLY); - RECIPIENT_PARAMETERS.update( - deps.storage, - |mut x| -> Result, ContractError> { - x.push(RecipientParameters { - recipient_address: deps.api.addr_validate(&user_address)?, - channel_id, - }); - - Ok(x) - }, - )?; - Ok(Response::new() .add_submessage(submsg) .add_attributes([("action", "try_swap_out")])) @@ -123,22 +103,37 @@ pub fn try_update_config( } fn get_wasm_msg( - deps: &Deps, + deps: DepsMut, + env: &Env, recipient_address: &str, mantaswap_msg: &mantaswap::msg::ExecuteMsg, funds: &Vec, + channel_id: &Option, ) -> Result { - let recipient = deps.api.addr_validate(recipient_address)?; let router = CONFIG.load(deps.storage)?.router; + let recipient_address = verify_ibc_parameters( + deps.as_ref(), + env, + mantaswap_msg, + channel_id, + recipient_address, + )?; + + let mut min_return_funds: Option> = None; + let swap_msg = match mantaswap_msg { mantaswap::msg::ExecuteMsg::Swap { stages, min_return, .. - } => mantaswap::msg::ExecuteMsg::Swap { - stages: stages.to_owned(), - recipient: Some(recipient), - min_return: min_return.to_owned(), - }, + } => { + min_return_funds = min_return.to_owned(); + + mantaswap::msg::ExecuteMsg::Swap { + stages: stages.to_owned(), + recipient: Some(env.contract.address.clone()), + min_return: min_return.to_owned(), + } + } _ => Err(ContractError::WrongMantaswapMsg)?, }; @@ -148,25 +143,64 @@ fn get_wasm_msg( funds: funds.to_owned(), }; + let min_return_funds = min_return_funds.ok_or(ContractError::CoinIsNotFound)?; + let Coin { denom, .. } = min_return_funds + .get(0) + .ok_or(ContractError::CoinIsNotFound)?; + + RECIPIENT_PARAMETERS.update( + deps.storage, + |mut x| -> Result, ContractError> { + x.push(RecipientParameters { + recipient_address, + channel_id: channel_id.to_owned(), + denom_out: denom.to_string(), + }); + + Ok(x) + }, + )?; + Ok(wasm_msg) } fn verify_ibc_parameters( + deps: Deps, + env: &Env, mantaswap_msg: &mantaswap::msg::ExecuteMsg, channel_id: &Option, -) -> Result<(), ContractError> { + recipient_address: &str, +) -> Result { + let address_parts = recipient_address.split('1').collect::>(); + let prefix = address_parts + .first() + .ok_or(ContractError::PrefixIsNotFound)?; + match mantaswap_msg { mantaswap::msg::ExecuteMsg::Swap { min_return: Some(coins), .. } => { - let Coin { denom, .. } = coins.get(0).ok_or(ContractError::CoinIsNotFound)?; - - if channel_id.is_some() && !denom.contains("ibc/") { - Err(ContractError::AssetIsNotIbcToken)?; + let Coin { denom, .. } = coins.first().ok_or(ContractError::CoinIsNotFound)?; + + if channel_id.is_some() && !(denom.contains("ibc/") && (prefix != &BASE_PREFIX)) { + Err(ContractError::WrongIbcParameters { + prefix: prefix.to_string(), + ibc_token: denom.to_string(), + channel_id: channel_id.to_owned(), + })?; } - Ok(()) + let address = if env.block.chain_id == CHAIN_ID_DEV { + deps.api.addr_validate(recipient_address)? + } else { + deps.api + .addr_validate(&get_addr_by_prefix(recipient_address, BASE_PREFIX)?)?; + + Addr::unchecked(recipient_address) + }; + + Ok(address) } _ => Err(ContractError::WrongMantaswapMsg)?, } diff --git a/contracts/eldorado-aggregator-kujira/src/actions/instantiate.rs b/contracts/eldorado-aggregator-kujira/src/actions/instantiate.rs index 648e545..2560dd9 100644 --- a/contracts/eldorado-aggregator-kujira/src/actions/instantiate.rs +++ b/contracts/eldorado-aggregator-kujira/src/actions/instantiate.rs @@ -14,14 +14,17 @@ const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); pub fn try_instantiate( deps: DepsMut, - _env: Env, + env: Env, info: MessageInfo, msg: InstantiateMsg, ) -> Result { let admin = &info.sender; let router = &deps.api.addr_validate(&msg.router_address)?; - CONFIG.save(deps.storage, &Config::new(admin, router))?; + CONFIG.save( + deps.storage, + &Config::new(admin, router, &env.block.chain_id), + )?; RECIPIENT_PARAMETERS.save(deps.storage, &vec![])?; diff --git a/contracts/eldorado-aggregator-kujira/src/actions/other.rs b/contracts/eldorado-aggregator-kujira/src/actions/other.rs index b6c933d..12170d5 100644 --- a/contracts/eldorado-aggregator-kujira/src/actions/other.rs +++ b/contracts/eldorado-aggregator-kujira/src/actions/other.rs @@ -85,6 +85,7 @@ fn parse_attributes( let RecipientParameters { recipient_address, channel_id, + .. } = recipient_parameters_list .get(0) .ok_or(ContractError::RecipientParametersAreNotFound)?; diff --git a/contracts/eldorado-aggregator-kujira/testnet.sh b/contracts/eldorado-aggregator-kujira/testnet.sh index aa2676e..55b6b46 100755 --- a/contracts/eldorado-aggregator-kujira/testnet.sh +++ b/contracts/eldorado-aggregator-kujira/testnet.sh @@ -25,7 +25,7 @@ KEYRING_PASSWORD="12345678" # instantiate smart contract -CONTRACT_CODE="2422" # tx_hash: 57810BD7144C6A4CC62CBFC1B3366282C79984575BF6E28BC1A112488E2F07F4 +CONTRACT_CODE="2448" # tx_hash: 33A8E5B92903329F7F9D62B1AD0C9B5E54D21F798DAF14A3E7F39E5D932908EE # INIT="{\"router_address\":\"$MANTASWAP_ROUTER_ADDRESS\"}" # yes $KEYRING_PASSWORD | $DAEMON tx wasm instantiate $CONTRACT_CODE "$INIT" --from "dapp" --label "$DIR_NAME_SNAKE-dev" $TXFLAG --admin $DAPP_ADDRESS @@ -34,7 +34,7 @@ CONTRACT_CODE="2422" # tx_hash: 57810BD7144C6A4CC62CBFC1B3366282C79984575BF6E28B # write data to file -CONTRACT_ADDRESS="kujira1mmhrcaxwe6qtcpnd7ua46qywwyndhpcfzrn8atyslfcwttjwkrcsq0v6f7" # tx_hash: 7506D5F07100EC0A9832AA25969B07861F88E153AB8FF7DE97348977AF62B58C +CONTRACT_ADDRESS="kujira1wlkn8px6y5jfp9suqusdjmnhysd4594qsju87694gl5mlckjwscs87sfdg" # tx_hash: 7870493843B6920847C5970B21E85E1DA7D91888BB77BA8097077E3C1F27C8EF # R="{ # \"PREFIX\":\"$PREFIX\", @@ -53,41 +53,40 @@ CONTRACT_ADDRESS="kujira1mmhrcaxwe6qtcpnd7ua46qywwyndhpcfzrn8atyslfcwttjwkrcsq0v # echo $CONFIG -# Execute SwapIn to swap 0.0001 USK -> KUJI and send to vault with memo -# tx_hash: DCE7D4B1E64C44530290515805041A36BD3BBF7B9F31CF5AEACAEA7F44EE6AFF -# 1) Find denoms by code here https://api.mantadao.app/whitelist -# mainnet: USK - factory/kujira1qk00h5atutpsv900x202pxx42npjr9thg58dnqpa72f2p7m2luase444a7/uusk, KUJI - ukuji -# testnet: USK - factory/kujira1r85reqy6h0lu02vyz0hnzhv5whsns55gdt4w0d7ft87utzk7u0wqr4ssll/uusk, KUJI - ukuji -# 2) Get contract payload sending POST request to https://api.mantadao.app/route -# Request body -# mainnet: {"input":{"denom":"factory/kujira1qk00h5atutpsv900x202pxx42npjr9thg58dnqpa72f2p7m2luase444a7/uusk","amount":"100","slippage":0.001},"output":{"denom":"ukuji"}} -# testnet: {"input":{"denom":"factory/kujira1r85reqy6h0lu02vyz0hnzhv5whsns55gdt4w0d7ft87utzk7u0wqr4ssll/uusk","amount":"100","slippage":0.001},"output":{"denom":"ukuji"}} -# We will get 'response' then 'response.routes[0].tx' will be 'MANTASWAP_MSG' -# mainnet: MANTASWAP_MSG="{\"swap\":{\"stages\":[[[\"kujira14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sl4e867\",\"ibc/295548A78785A1007F232DE286149A6FF512F180AF5657780FC89C009E2C348F\"]],[[\"kujira1rwx6w02alc4kaz7xpyg3rlxpjl4g63x5jq292mkxgg65zqpn5llq202vh5\",\"factory/kujira1qk00h5atutpsv900x202pxx42npjr9thg58dnqpa72f2p7m2luase444a7/uusk\"]]],\"min_return\":[{\"denom\": \"ukuji\",\"amount\": \"1603\"}]}}" -# testnet: -MANTASWAP_MSG='{"swap":{"stages":[[["kujira1wl003xxwqltxpg5pkre0rl605e406ktmq5gnv0ngyjamq69mc2kqm06ey6","factory/kujira1r85reqy6h0lu02vyz0hnzhv5whsns55gdt4w0d7ft87utzk7u0wqr4ssll/uusk"]]],"min_return":[{"denom":"ukuji","amount":"80"}]}}' -# 3) add vault address to compose 'SWAP_IN_MSG' -SWAP_IN_MSG="{\"swap_in\":{\"vault_address\":\"$VAULT_ADDRESS\",\"mantaswap_msg\":$MANTASWAP_MSG}}" -# 4) add funds -# mainnet: FUNDS="100factory/kujira1qk00h5atutpsv900x202pxx42npjr9thg58dnqpa72f2p7m2luase444a7/uusk" -# testnet: -FUNDS="100factory/kujira1r85reqy6h0lu02vyz0hnzhv5whsns55gdt4w0d7ft87utzk7u0wqr4ssll/uusk" -# 5) specify memo and call the contract -MEMO=":BTC:yourbtcaddress" -SWAP_IN_RES=$(yes $KEYRING_PASSWORD | $DAEMON tx wasm execute $CONTRACT_ADDRESS "$SWAP_IN_MSG" --from=$(echo $DAPP_ADDRESS) --amount "$FUNDS" --note "$MEMO" $TXFLAG --output json) -echo $SWAP_IN_RES - - -# Execute SwapOut to swap 0.0001 KUJI -> USK and send to user -# tx_hash: 9C313E5F80BEBB811332783F26A0A1FEA2F5810007BAD05E501C2FE92CBBA729 -# For SwapOut we have same steps but added optional IBC channel_id parameter required to transfer IBC token -# to native network. It can be found here https://raw.githubusercontent.com/Team-Kujira/kujira.js/master/src/resources/tokens.json -# For example we have 'usei' on kujira with IBC denom 'ibc/EB7D94B1B3D878F8461959A5A21DBB9D7EC6989F1347D67CC002805E772FE3F9' -# The path is "transfer/channel-4" where 'channel-4' is channel_id. -# There is no infra for IBC transfer on testnet. Then skip channel_id parameter -MANTASWAP_MSG='{"swap":{"stages":[[["kujira1wl003xxwqltxpg5pkre0rl605e406ktmq5gnv0ngyjamq69mc2kqm06ey6","ukuji"]]],"min_return":[{"denom":"factory/kujira1r85reqy6h0lu02vyz0hnzhv5whsns55gdt4w0d7ft87utzk7u0wqr4ssll/uusk","amount":"110"}]}}' -SWAP_OUT_MSG="{\"swap_out\":{\"user_address\":\"$VAULT_ADDRESS\",\"mantaswap_msg\":$MANTASWAP_MSG}}" -FUNDS="100ukuji" -SWAP_OUT_RES=$(yes $KEYRING_PASSWORD | $DAEMON tx wasm execute $CONTRACT_ADDRESS "$SWAP_OUT_MSG" --from=$(echo $DAPP_ADDRESS) --amount "$FUNDS" $TXFLAG --output json) -echo $SWAP_OUT_RES - +# # Execute SwapIn to swap 0.0001 USK -> KUJI and send to vault with memo +# # tx_hash: 183CA82D8DA84692053D47EB85E496B8C7EC1B1DCF29005C04C4B02D928244B5 +# # 1) Find denoms by code here https://api.mantadao.app/whitelist +# # mainnet: USK - factory/kujira1qk00h5atutpsv900x202pxx42npjr9thg58dnqpa72f2p7m2luase444a7/uusk, KUJI - ukuji +# # testnet: USK - factory/kujira1r85reqy6h0lu02vyz0hnzhv5whsns55gdt4w0d7ft87utzk7u0wqr4ssll/uusk, KUJI - ukuji +# # 2) Get contract payload sending POST request to https://api.mantadao.app/route +# # Request body +# # mainnet: {"input":{"denom":"factory/kujira1qk00h5atutpsv900x202pxx42npjr9thg58dnqpa72f2p7m2luase444a7/uusk","amount":"100","slippage":0.001},"output":{"denom":"ukuji"}} +# # testnet: {"input":{"denom":"factory/kujira1r85reqy6h0lu02vyz0hnzhv5whsns55gdt4w0d7ft87utzk7u0wqr4ssll/uusk","amount":"100","slippage":0.001},"output":{"denom":"ukuji"}} +# # We will get 'response' then 'response.routes[0].tx' will be 'MANTASWAP_MSG' +# # mainnet: MANTASWAP_MSG="{\"swap\":{\"stages\":[[[\"kujira14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sl4e867\",\"ibc/295548A78785A1007F232DE286149A6FF512F180AF5657780FC89C009E2C348F\"]],[[\"kujira1rwx6w02alc4kaz7xpyg3rlxpjl4g63x5jq292mkxgg65zqpn5llq202vh5\",\"factory/kujira1qk00h5atutpsv900x202pxx42npjr9thg58dnqpa72f2p7m2luase444a7/uusk\"]]],\"min_return\":[{\"denom\": \"ukuji\",\"amount\": \"1603\"}]}}" +# # testnet: +# MANTASWAP_MSG='{"swap":{"stages":[[["kujira1wl003xxwqltxpg5pkre0rl605e406ktmq5gnv0ngyjamq69mc2kqm06ey6","factory/kujira1r85reqy6h0lu02vyz0hnzhv5whsns55gdt4w0d7ft87utzk7u0wqr4ssll/uusk"]]],"min_return":[{"denom":"ukuji","amount":"80"}]}}' +# # 3) add vault address to compose 'SWAP_IN_MSG' +# SWAP_IN_MSG="{\"swap_in\":{\"vault_address\":\"$VAULT_ADDRESS\",\"mantaswap_msg\":$MANTASWAP_MSG}}" +# # 4) add funds +# # mainnet: FUNDS="100factory/kujira1qk00h5atutpsv900x202pxx42npjr9thg58dnqpa72f2p7m2luase444a7/uusk" +# # testnet: +# FUNDS="100factory/kujira1r85reqy6h0lu02vyz0hnzhv5whsns55gdt4w0d7ft87utzk7u0wqr4ssll/uusk" +# # 5) specify memo and call the contract +# MEMO=":BTC:yourbtcaddress" +# SWAP_IN_RES=$(yes $KEYRING_PASSWORD | $DAEMON tx wasm execute $CONTRACT_ADDRESS "$SWAP_IN_MSG" --from=$(echo $DAPP_ADDRESS) --amount "$FUNDS" --note "$MEMO" $TXFLAG --output json) +# echo $SWAP_IN_RES + + +# # Execute SwapOut to swap 0.0001 KUJI -> USK and send to user +# # tx_hash: 412BC583C28D59DDA77FA6E78DF536200BD59E09EC015F8305197FD0A06124E0 +# # For SwapOut we have same steps but added optional IBC channel_id parameter required to transfer IBC token +# # to native network. It can be found here https://raw.githubusercontent.com/Team-Kujira/kujira.js/master/src/resources/tokens.json +# # For example we have 'usei' on kujira with IBC denom 'ibc/EB7D94B1B3D878F8461959A5A21DBB9D7EC6989F1347D67CC002805E772FE3F9' +# # The path is "transfer/channel-4" where 'channel-4' is channel_id. +# # There is no infra for IBC transfer on testnet. Then skip channel_id parameter +# MANTASWAP_MSG='{"swap":{"stages":[[["kujira1wl003xxwqltxpg5pkre0rl605e406ktmq5gnv0ngyjamq69mc2kqm06ey6","ukuji"]]],"min_return":[{"denom":"factory/kujira1r85reqy6h0lu02vyz0hnzhv5whsns55gdt4w0d7ft87utzk7u0wqr4ssll/uusk","amount":"110"}]}}' +# SWAP_OUT_MSG="{\"swap_out\":{\"user_address\":\"$VAULT_ADDRESS\",\"mantaswap_msg\":$MANTASWAP_MSG}}" +# FUNDS="100ukuji" +# SWAP_OUT_RES=$(yes $KEYRING_PASSWORD | $DAEMON tx wasm execute $CONTRACT_ADDRESS "$SWAP_OUT_MSG" --from=$(echo $DAPP_ADDRESS) --amount "$FUNDS" $TXFLAG --output json) +# echo $SWAP_OUT_RES diff --git a/contracts/eldorado-aggregator-osmosis/src/actions/execute.rs b/contracts/eldorado-aggregator-osmosis/src/actions/execute.rs index aee1ae1..86dc965 100644 --- a/contracts/eldorado-aggregator-osmosis/src/actions/execute.rs +++ b/contracts/eldorado-aggregator-osmosis/src/actions/execute.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{CosmosMsg, Deps, DepsMut, Env, MessageInfo, Response, SubMsg, Uint128}; +use cosmwasm_std::{Addr, CosmosMsg, Deps, DepsMut, Env, MessageInfo, Response, SubMsg, Uint128}; use osmosis_std::types::{ cosmos::base::v1beta1::Coin, @@ -11,15 +11,16 @@ use osmosis_std::types::{ use cw_utils::{must_pay, nonpayable, one_coin}; use eldorado_base::{ - converters::{str_to_dec, u128_to_dec}, + converters::get_addr_by_prefix, eldorado_aggregator_osmosis::state::{ - Config, CONFIG, DENOM_OSMO, RECIPIENT_PARAMETERS, SWAP_IN_REPLY, SWAP_OUT_REPLY, + Config, BASE_DENOM, BASE_PREFIX, CONFIG, RECIPIENT_PARAMETERS, SWAP_IN_REPLY, + SWAP_OUT_REPLY, }, error::ContractError, types::RecipientParameters, }; -use crate::actions::query::query_pool; +use crate::actions::query::{estimate_swap_exact_amount_in, query_pool}; pub fn try_swap_in( deps: DepsMut, @@ -30,8 +31,9 @@ pub fn try_swap_in( ) -> Result { let coin = one_coin(&info).map_err(|e| ContractError::CustomError { val: e.to_string() })?; let swap_msg = get_swap_msg( - &deps.as_ref(), + deps, &env, + &vault_address, coin.amount, &coin.denom, pool_id, @@ -39,18 +41,6 @@ pub fn try_swap_in( )?; let submsg = SubMsg::reply_on_success(swap_msg, SWAP_IN_REPLY); - RECIPIENT_PARAMETERS.update( - deps.storage, - |mut x| -> Result, ContractError> { - x.push(RecipientParameters { - recipient_address: deps.api.addr_validate(&vault_address)?, - channel_id: None, - }); - - Ok(x) - }, - )?; - Ok(Response::new() .add_submessage(submsg) .add_attributes([("action", "try_swap_in")])) @@ -64,30 +54,19 @@ pub fn try_swap_out( pool_id: u64, channel_id: Option, ) -> Result { - let amount = must_pay(&info, DENOM_OSMO) + let amount = must_pay(&info, BASE_DENOM) .map_err(|e| ContractError::CustomError { val: e.to_string() })?; let swap_msg = get_swap_msg( - &deps.as_ref(), + deps, &env, + &user_address, amount, - DENOM_OSMO, + BASE_DENOM, pool_id, &channel_id, )?; let submsg = SubMsg::reply_on_success(swap_msg, SWAP_OUT_REPLY); - RECIPIENT_PARAMETERS.update( - deps.storage, - |mut x| -> Result, ContractError> { - x.push(RecipientParameters { - recipient_address: deps.api.addr_validate(&user_address)?, - channel_id, - }); - - Ok(x) - }, - )?; - Ok(Response::new() .add_submessage(submsg) .add_attributes([("action", "try_swap_out")])) @@ -123,8 +102,9 @@ pub fn try_update_config( } fn get_swap_msg( - deps: &Deps, + deps: DepsMut, env: &Env, + recipient_address: &str, amount_in: Uint128, denom_in: &str, pool_id: u64, @@ -132,35 +112,30 @@ fn get_swap_msg( ) -> Result { let Pool { id, pool_assets, .. - } = query_pool(deps.to_owned(), env.to_owned(), pool_id)?; + } = query_pool(deps.as_ref(), pool_id)?; let asset_list = pool_assets .into_iter() .map(|x| -> Result { x.token.ok_or(ContractError::CoinIsNotFound) }) .collect::, ContractError>>()?; - let asset_in = asset_list - .iter() - .find(|x| x.denom == denom_in) - .ok_or(ContractError::CoinIsNotFound)?; - let asset_out = asset_list .iter() .find(|x| x.denom != denom_in) .ok_or(ContractError::CoinIsNotFound)?; + let denom_out = &asset_out.denom; - verify_ibc_parameters(&asset_out.denom, channel_id)?; - - let token_out_min_amount = (str_to_dec("0.9") - * u128_to_dec(amount_in) - * (str_to_dec(&asset_in.amount) / str_to_dec(&asset_in.amount))) - .to_string(); + let recipient_address = + verify_ibc_parameters(deps.as_ref(), denom_out, channel_id, recipient_address)?; let routes = vec![SwapAmountInRoute { pool_id: id, - token_out_denom: asset_out.denom.to_owned(), + token_out_denom: denom_out.to_string(), }]; + let token_out_min_amount = + estimate_swap_exact_amount_in(deps.as_ref(), id, amount_in, denom_in, &routes)?; + let swap_msg = MsgSwapExactAmountIn { sender: env.contract.address.to_string(), routes, @@ -171,16 +146,43 @@ fn get_swap_msg( token_out_min_amount, }; + RECIPIENT_PARAMETERS.update( + deps.storage, + |mut x| -> Result, ContractError> { + x.push(RecipientParameters { + recipient_address, + channel_id: channel_id.to_owned(), + denom_out: denom_out.to_string(), + }); + + Ok(x) + }, + )?; + Ok(swap_msg.into()) } fn verify_ibc_parameters( + deps: Deps, ibc_token: &str, channel_id: &Option, -) -> Result<(), ContractError> { - if channel_id.is_some() && !ibc_token.contains("ibc/") { - Err(ContractError::AssetIsNotIbcToken)?; + recipient_address: &str, +) -> Result { + let address_parts = recipient_address.split('1').collect::>(); + let prefix = address_parts + .first() + .ok_or(ContractError::PrefixIsNotFound)?; + + if channel_id.is_some() && (!ibc_token.contains("ibc/") || (prefix == &BASE_PREFIX)) { + Err(ContractError::WrongIbcParameters { + prefix: prefix.to_string(), + ibc_token: ibc_token.to_string(), + channel_id: channel_id.to_owned(), + })?; } - Ok(()) + deps.api + .addr_validate(&get_addr_by_prefix(recipient_address, BASE_PREFIX)?)?; + + Ok(Addr::unchecked(recipient_address)) } diff --git a/contracts/eldorado-aggregator-osmosis/src/actions/other.rs b/contracts/eldorado-aggregator-osmosis/src/actions/other.rs index 6d05cd7..15c7343 100644 --- a/contracts/eldorado-aggregator-osmosis/src/actions/other.rs +++ b/contracts/eldorado-aggregator-osmosis/src/actions/other.rs @@ -1,10 +1,12 @@ use std::str::FromStr; use cosmwasm_std::{ - Addr, BankMsg, Coin, CosmosMsg, DepsMut, Env, Event, IbcMsg, IbcTimeout, Response, + Addr, BankMsg, Coin, CosmosMsg, DepsMut, Env, IbcMsg, IbcTimeout, Response, SubMsgResponse, SubMsgResult, Uint128, }; +use osmosis_std::types::osmosis::gamm::v1beta1::MsgSwapExactAmountInResponse; + use eldorado_base::{ eldorado_aggregator_osmosis::{ msg::MigrateMsg, @@ -85,6 +87,7 @@ fn parse_attributes( let RecipientParameters { recipient_address, channel_id, + denom_out, } = recipient_parameters_list .get(0) .ok_or(ContractError::RecipientParametersAreNotFound)?; @@ -94,51 +97,30 @@ fn parse_attributes( RECIPIENT_PARAMETERS.save(deps.storage, &recipient_parameters_tail)?; - let res = result - .to_owned() - .into_result() - .map_err(|e| ContractError::CustomError { val: e })?; - - let mut transfer_events: Vec = vec![]; - - for event in res.events { - if event.ty.contains("transfer") { - for attr in &event.attributes { - if (attr.key == "recipient") && (attr.value == env.contract.address.as_ref()) { - transfer_events.push(event.clone()); - break; - } - } - } - } + let mut amount_out_string: Option = None; - let event = transfer_events - .last() - .ok_or(ContractError::EventIsNotFound)?; + if let SubMsgResult::Ok(SubMsgResponse { data: Some(b), .. }) = result.to_owned() { + let MsgSwapExactAmountInResponse { token_out_amount } = + b.try_into().map_err(ContractError::Std)?; - let coin_string = &event - .attributes - .iter() - .find(|x| x.key == "amount") - .ok_or(ContractError::AttributeIsNotFound)? - .value; + amount_out_string = Some(token_out_amount); + } - let Coin { denom, amount } = Coin::from_str(coin_string) - .map_err(|e| ContractError::CustomError { val: e.to_string() })?; + let amount_out = Uint128::from_str(&amount_out_string.ok_or(ContractError::CoinIsNotFound)?)?; let balance = deps .querier - .query_balance(env.contract.address.as_str(), &denom)?; + .query_balance(env.contract.address.as_str(), denom_out)?; - if balance.amount < amount { + if balance.amount < amount_out { Err(ContractError::BalanceIsNotEnough { - symbol: denom.clone(), + symbol: denom_out.clone(), })?; } Ok(( - amount, - denom, + amount_out, + denom_out.to_string(), recipient_address.to_owned(), channel_id.to_owned(), )) diff --git a/contracts/eldorado-aggregator-osmosis/src/actions/query.rs b/contracts/eldorado-aggregator-osmosis/src/actions/query.rs index 960789c..9920d2f 100644 --- a/contracts/eldorado-aggregator-osmosis/src/actions/query.rs +++ b/contracts/eldorado-aggregator-osmosis/src/actions/query.rs @@ -1,13 +1,20 @@ -use cosmwasm_std::{Deps, Env, StdResult}; +use cosmwasm_std::{Deps, Env, StdResult, Uint128}; -use osmosis_std::types::osmosis::{gamm::v1beta1::Pool, poolmanager::v1beta1::PoolmanagerQuerier}; +use osmosis_std::types::osmosis::{ + gamm::v1beta1::Pool, + poolmanager::v1beta1::{PoolmanagerQuerier, SwapAmountInRoute}, +}; use eldorado_base::{ eldorado_aggregator_osmosis::state::{Config, CONFIG}, error::{to_std_err, ContractError}, }; -pub fn query_pool(deps: Deps, _env: Env, pool_id: u64) -> StdResult { +pub fn query_config(deps: Deps, _env: Env) -> StdResult { + CONFIG.load(deps.storage) +} + +pub fn query_pool(deps: Deps, pool_id: u64) -> StdResult { PoolmanagerQuerier::new(&deps.querier) .pool(pool_id)? .pool @@ -16,6 +23,18 @@ pub fn query_pool(deps: Deps, _env: Env, pool_id: u64) -> StdResult { .map_err(|_| to_std_err(ContractError::PoolsCanNotBeParsed)) } -pub fn query_config(deps: Deps, _env: Env) -> StdResult { - CONFIG.load(deps.storage) +pub fn estimate_swap_exact_amount_in( + deps: Deps, + pool_id: u64, + amount_in: Uint128, + denom_in: &str, + routes: &Vec, +) -> StdResult { + Ok(PoolmanagerQuerier::new(&deps.querier) + .estimate_swap_exact_amount_in( + pool_id, + format!("{}{}", amount_in, denom_in), + routes.to_owned(), + )? + .token_out_amount) } diff --git a/contracts/eldorado-aggregator-osmosis/testnet.sh b/contracts/eldorado-aggregator-osmosis/testnet.sh index 462f89f..f31bc1a 100755 --- a/contracts/eldorado-aggregator-osmosis/testnet.sh +++ b/contracts/eldorado-aggregator-osmosis/testnet.sh @@ -24,7 +24,7 @@ KEYRING_PASSWORD="12345678" # instantiate smart contract -CONTRACT_CODE="4261" # tx_hash: E67BADEC801E6479EE30843FF8C4CF3D2DE3B1B4E14A2D62C169BDD091159C18 +CONTRACT_CODE="4288" # tx_hash: BFF9C1317F5818830A0169BB6AD1FA965CB10E779FD143DDC898B2C8912370A1 # INIT="{}" # yes $KEYRING_PASSWORD | $DAEMON tx wasm instantiate $CONTRACT_CODE "$INIT" --from "dapp" --label "$DIR_NAME_SNAKE-dev" $TXFLAG --admin $DAPP_ADDRESS @@ -33,7 +33,7 @@ CONTRACT_CODE="4261" # tx_hash: E67BADEC801E6479EE30843FF8C4CF3D2DE3B1B4E14A2D62 # write data to file -CONTRACT_ADDRESS="osmo17xvvelv6wmqvrjehn6d5kdsm4xymgux3g67sfd3ajnknzuatwffs0ehaw8" # tx_hash: 0A237B159874470BEDD006A771ED7764C4D2CD65F3359727F4EAAE217D4A07EF +CONTRACT_ADDRESS="osmo1pmhdtae4zyvjveva9f6a9tgenslyr46w5ws67u7447473cn9gqxqhl92d7" # tx_hash: A990D3E8E257565BF3695247989EB7D8AAE086BB91472708618A380C1FBCDCAC # R="{ # \"PREFIX\":\"$PREFIX\", @@ -56,32 +56,39 @@ CONTRACT_ADDRESS="osmo17xvvelv6wmqvrjehn6d5kdsm4xymgux3g67sfd3ajnknzuatwffs0ehaw # SWAP_RES=$(yes $KEYRING_PASSWORD | $DAEMON tx gamm swap-exact-amount-in "100$ATOM" "1" --swap-route-denoms "uosmo" --swap-route-pool-ids 151 --from=$(echo $DAPP_ADDRESS) $TXFLAG --output json) # echo $SWAP_RES -# Execute SwapIn to swap 0.0001 ATOM -> OSMO and send to vault with memo -# tx_hash: -# 1) add vault address to compose 'SWAP_IN_MSG' -POOL_ID=151 -SWAP_IN_MSG="{\"swap_in\":{\"vault_address\":\"$VAULT_ADDRESS\",\"pool_id\":$POOL_ID}}" -echo $SWAP_IN_MSG -# 2) add funds (get denom by symbol here https://raw.githubusercontent.com/osmosis-labs/assetlists/main/osmosis-1/osmosis-1.assetlist.json) -# mainnet: FUNDS="100ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2" -# testnet: -FUNDS="100ibc/B28CFD38D84A480EF2A03AC575DCB05004D934A603A5A642888847BCDA6340C0" -# 3) specify memo and call the contract -MEMO=":BTC:yourbtcaddress" -SWAP_IN_RES=$(yes $KEYRING_PASSWORD | $DAEMON tx wasm execute $CONTRACT_ADDRESS "$SWAP_IN_MSG" --from=$(echo $DAPP_ADDRESS) --amount "$FUNDS" --note "$MEMO" $TXFLAG --output json) -echo $SWAP_IN_RES - - -# # Execute SwapOut to swap 0.0001 OSMO -> ATOM and send to user -# # tx_hash: -# # For SwapOut we have same steps but added optional IBC channel_id parameter required to transfer IBC token -# # to native network. It also can be found here https://raw.githubusercontent.com/osmosis-labs/assetlists/main/osmosis-1/osmosis-1.assetlist.json -# # For example we have 'uatom' on Osmosis with IBC denom 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2' -# # The channel_id is 'channel-0'. -# # There is no infra for IBC transfer on testnet. Then skip channel_id parameter -# DENOM_OUT="ibc/B28CFD38D84A480EF2A03AC575DCB05004D934A603A5A642888847BCDA6340C0" -# SWAP_OUT_MSG="{\"swap_out\":{\"user_address\":\"$VAULT_ADDRESS\",\"denom_out\":$DENOM_OUT}}" +# # Execute SwapIn to swap 0.0001 ATOM -> OSMO and send to vault with memo +# # tx_hash: 5CD9496FE4B2497A6DB2E585F6884A08CE3B2627362F31CA337129BC07C7CA2F +# # 1) add vault address to compose 'SWAP_IN_MSG' +# POOL_ID=151 +# SWAP_IN_MSG="{\"swap_in\":{\"vault_address\":\"$VAULT_ADDRESS\",\"pool_id\":$POOL_ID}}" +# # 2) add funds (get denom by symbol here https://raw.githubusercontent.com/osmosis-labs/assetlists/main/osmosis-1/osmosis-1.assetlist.json) +# # mainnet: FUNDS="100ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2" +# # testnet: +# FUNDS="100ibc/B28CFD38D84A480EF2A03AC575DCB05004D934A603A5A642888847BCDA6340C0" +# # 3) specify memo and call the contract +# MEMO=":BTC:yourbtcaddress" +# SWAP_IN_RES=$(yes $KEYRING_PASSWORD | $DAEMON tx wasm execute $CONTRACT_ADDRESS "$SWAP_IN_MSG" --from=$(echo $DAPP_ADDRESS) --amount "$FUNDS" --note "$MEMO" $TXFLAG --output json) +# echo $SWAP_IN_RES + + +# Execute SwapOut to swap 0.0001 OSMO -> ATOM and send to user +# For SwapOut we have same steps but added optional IBC channel_id parameter required to transfer IBC token +# to native network. It also can be found here https://raw.githubusercontent.com/osmosis-labs/assetlists/main/osmosis-1/osmosis-1.assetlist.json +# For example on mainnet we have 'uatom' on Osmosis with IBC denom +# 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2', the channel_id is 'channel-0'. + +# # Osmisis -> Osmosis, tx_hash: 902DB2A379C4F129CDB3FF3169B158B172A072290065D3276FAB6B1C3FCCAF3E +# POOL_ID=151 +# SWAP_OUT_MSG="{\"swap_out\":{\"user_address\":\"$VAULT_ADDRESS\",\"pool_id\":$POOL_ID}}" # FUNDS="100uosmo" # SWAP_OUT_RES=$(yes $KEYRING_PASSWORD | $DAEMON tx wasm execute $CONTRACT_ADDRESS "$SWAP_OUT_MSG" --from=$(echo $DAPP_ADDRESS) --amount "$FUNDS" $TXFLAG --output json) # echo $SWAP_OUT_RES +# # Osmosis -> Cosmos Hub, tx_hash: 8D48FF0C3DDADE559E426CE5A49EE429528F801D6713A1024438F54D98B14483 +# USER_ADDRESS_COSMOS_HUB="cosmos1chgwz55h9kepjq0fkj5supl2ta3nwu63327q35" +# CHANNEL_ID="channel-1497" +# POOL_ID=151 +# SWAP_OUT_MSG="{\"swap_out\":{\"user_address\":\"$USER_ADDRESS_COSMOS_HUB\",\"pool_id\":$POOL_ID,\"channel_id\":\"$CHANNEL_ID\"}}" +# FUNDS="100uosmo" +# SWAP_OUT_RES=$(yes $KEYRING_PASSWORD | $DAEMON tx wasm execute $CONTRACT_ADDRESS "$SWAP_OUT_MSG" --from=$(echo $DAPP_ADDRESS) --amount "$FUNDS" $TXFLAG --output json) +# echo $SWAP_OUT_RES diff --git a/packages/eldorado-base/Cargo.toml b/packages/eldorado-base/Cargo.toml index 190714f..198ef38 100644 --- a/packages/eldorado-base/Cargo.toml +++ b/packages/eldorado-base/Cargo.toml @@ -19,4 +19,5 @@ cosmwasm-std = { workspace = true } cw-storage-plus = { workspace = true } serde = { workspace = true } thiserror = { workspace = true } -kujira = { workspace = true } \ No newline at end of file +kujira = { workspace = true } +bech32 = { workspace = true } \ No newline at end of file diff --git a/packages/eldorado-base/src/converters.rs b/packages/eldorado-base/src/converters.rs index cb99df4..465ca26 100644 --- a/packages/eldorado-base/src/converters.rs +++ b/packages/eldorado-base/src/converters.rs @@ -1,7 +1,9 @@ -use cosmwasm_std::{Decimal, Decimal256, Uint128}; +use cosmwasm_std::{Decimal, Decimal256, StdError, StdResult, Uint128}; use std::str::FromStr; +use bech32::{decode, encode, Variant}; + pub fn str_to_dec(s: &str) -> Decimal { Decimal::from_str(s).unwrap() } @@ -56,3 +58,10 @@ pub fn u128_vec_to_uint128_vec(u128_vec: &[u128]) -> Vec { .map(|&x| Uint128::from(x)) .collect::>() } + +pub fn get_addr_by_prefix(address: &str, prefix: &str) -> StdResult { + let (_hrp, data, _) = decode(address).map_err(|e| StdError::generic_err(e.to_string()))?; + let new_address = + encode(prefix, data, Variant::Bech32).map_err(|e| StdError::generic_err(e.to_string()))?; + Ok(new_address) +} diff --git a/packages/eldorado-base/src/eldorado_aggregator_kujira/state.rs b/packages/eldorado-base/src/eldorado_aggregator_kujira/state.rs index 5f56137..7dc5779 100644 --- a/packages/eldorado-base/src/eldorado_aggregator_kujira/state.rs +++ b/packages/eldorado-base/src/eldorado_aggregator_kujira/state.rs @@ -5,7 +5,9 @@ use cw_storage_plus::Item; use crate::types::RecipientParameters; pub const TIMEOUT_IN_MINS: u8 = 15; -pub const DENOM_KUJI: &str = "ukuji"; +pub const BASE_DENOM: &str = "ukuji"; +pub const BASE_PREFIX: &str = "kujira"; +pub const CHAIN_ID_DEV: &str = "devnet-1"; pub const SWAP_IN_REPLY: u64 = 1; pub const SWAP_OUT_REPLY: u64 = 2; @@ -16,14 +18,16 @@ pub struct Config { pub admin: Addr, pub router: Addr, pub ibc_timeout: u64, + pub chain_id: String, } impl Config { - pub fn new(admin: &Addr, router: &Addr) -> Self { + pub fn new(admin: &Addr, router: &Addr, chain_id: &str) -> Self { Self { admin: admin.to_owned(), router: router.to_owned(), ibc_timeout: (TIMEOUT_IN_MINS as u64) * 60, // timeout in seconds + chain_id: chain_id.to_string(), } } } diff --git a/packages/eldorado-base/src/eldorado_aggregator_osmosis/state.rs b/packages/eldorado-base/src/eldorado_aggregator_osmosis/state.rs index e318b20..a1c37bb 100644 --- a/packages/eldorado-base/src/eldorado_aggregator_osmosis/state.rs +++ b/packages/eldorado-base/src/eldorado_aggregator_osmosis/state.rs @@ -5,7 +5,8 @@ use cw_storage_plus::Item; use crate::types::RecipientParameters; pub const TIMEOUT_IN_MINS: u8 = 15; -pub const DENOM_OSMO: &str = "uosmo"; +pub const BASE_DENOM: &str = "uosmo"; +pub const BASE_PREFIX: &str = "osmo"; pub const SWAP_IN_REPLY: u64 = 1; pub const SWAP_OUT_REPLY: u64 = 2; diff --git a/packages/eldorado-base/src/error.rs b/packages/eldorado-base/src/error.rs index eae1fca..5f0a686 100644 --- a/packages/eldorado-base/src/error.rs +++ b/packages/eldorado-base/src/error.rs @@ -48,12 +48,19 @@ pub enum ContractError { #[error("channel_id is not found!")] ChannelIdIsNotFound, - #[error("The asset is not IBC token!")] - AssetIsNotIbcToken, + #[error("Wrong IBC parameters: prefix - {prefix:?}, ibc_token - {ibc_token:?}, chain_id - {channel_id:?}!")] + WrongIbcParameters { + prefix: String, + ibc_token: String, + channel_id: Option, + }, #[error("Coin is not found!")] CoinIsNotFound, + #[error("Prefix is not found!")] + PrefixIsNotFound, + // eldorado_aggregator_osmosis #[error("Pools can not be parsed!")] PoolsCanNotBeParsed, diff --git a/packages/eldorado-base/src/types.rs b/packages/eldorado-base/src/types.rs index fd1689d..1dc5308 100644 --- a/packages/eldorado-base/src/types.rs +++ b/packages/eldorado-base/src/types.rs @@ -5,4 +5,5 @@ use cosmwasm_std::Addr; pub struct RecipientParameters { pub recipient_address: Addr, pub channel_id: Option, + pub denom_out: String, } diff --git a/tests/src/eldorado_aggregator_kujira.rs b/tests/src/eldorado_aggregator_kujira.rs index d9811b9..3e04f31 100644 --- a/tests/src/eldorado_aggregator_kujira.rs +++ b/tests/src/eldorado_aggregator_kujira.rs @@ -4,7 +4,10 @@ use speculoos::assert_that; use kujira::Denom; -use eldorado_base::{eldorado_aggregator_kujira::state::Config, mantaswap::msg::ExecuteMsg}; +use eldorado_base::{ + eldorado_aggregator_kujira::state::{Config, CHAIN_ID_DEV}, + mantaswap::msg::ExecuteMsg, +}; use crate::helpers::{ eldorado_aggregator_kujira::EldoradoAggregatorKujiraExtension, @@ -381,7 +384,9 @@ fn swap_out_ibc_token_without_ibc_channel() { } #[test] -#[should_panic(expected = "The asset is not IBC token!")] +#[should_panic( + expected = "Wrong IBC parameters: prefix - \"alice\", ibc_token - \"factory/uusk\", chain_id - Some(\"channel-0\")" +)] fn swap_out_ibc_channel_without_ibc_token() { let mut project = Project::new(); @@ -480,12 +485,14 @@ fn update_config_default() { admin: ProjectAccount::Admin.to_address(), router: project.get_mantaswap_router_address(), ibc_timeout: 15 * 60, + chain_id: String::from(CHAIN_ID_DEV), }); assert_that(&config_after).is_equal_to(&Config { admin: ProjectAccount::Admin.to_address(), router: ProjectAccount::Owner.to_address(), ibc_timeout: 5 * 60, + chain_id: String::from(CHAIN_ID_DEV), }); } diff --git a/tests/src/helpers/suite/core.rs b/tests/src/helpers/suite/core.rs index 64749bb..02fd732 100644 --- a/tests/src/helpers/suite/core.rs +++ b/tests/src/helpers/suite/core.rs @@ -4,6 +4,8 @@ use cw_multi_test::{App, AppResponse, Executor}; use serde::Serialize; use strum::IntoEnumIterator; +use eldorado_base::eldorado_aggregator_kujira::state::CHAIN_ID_DEV; + use crate::helpers::suite::{ codes::WithCodes, types::{GetDecimals, ProjectAccount, ProjectCoin, ToAddress, WrappedResponse}, @@ -53,6 +55,10 @@ impl Project { // create app and distribute coins to accounts let mut project = Self::create_project_with_balances(); + project + .app + .update_block(|block| block.chain_id = String::from(CHAIN_ID_DEV)); + // register contracts code // packages let mantaswap_mocks_code_id = project.store_mantaswap_mocks_code();