diff --git a/.changelog/unreleased/features/4133-osmosis-swaps.md b/.changelog/unreleased/features/4133-osmosis-swaps.md deleted file mode 100644 index a6cd190100..0000000000 --- a/.changelog/unreleased/features/4133-osmosis-swaps.md +++ /dev/null @@ -1,4 +0,0 @@ -- Integrate Namada and Osmosis, to allow swapping assets privately. Osmosis - is leveraged for its liquidity and DEX capabilities, while Namada is - leveraged for its shielded pool (i.e. MASP) and privacy guarantees. - ([\#4133](https://github.com/anoma/namada/pull/4133)) \ No newline at end of file diff --git a/.github/workflows/scripts/e2e.json b/.github/workflows/scripts/e2e.json index 30046d7243..c63422bf67 100644 --- a/.github/workflows/scripts/e2e.json +++ b/.github/workflows/scripts/e2e.json @@ -9,8 +9,6 @@ "e2e::ibc_tests::ibc_pfm_happy_flows": 485, "e2e::ibc_tests::ibc_pfm_unhappy_flows": 485, "e2e::ibc_tests::ibc_upgrade_client": 280, - "e2e::ibc_tests::ibc_shielded_recv_middleware_happy_flow": 280, - "e2e::ibc_tests::ibc_shielded_recv_middleware_unhappy_flow": 280, "e2e::eth_bridge_tests::test_add_to_bridge_pool": 10, "e2e::ledger_tests::double_signing_gets_slashed": 12, "e2e::ledger_tests::ledger_many_txs_in_a_block": 55, diff --git a/Cargo.lock b/Cargo.lock index 77940026d3..df2c54c921 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3788,90 +3788,10 @@ dependencies = [ "syn 2.0.96", ] -[[package]] -name = "ibc-middleware-module" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=module/v0.1.0#3d3b436f7c58000c7498d68e88c15a955433a619" -dependencies = [ - "ibc-core-channel-types", - "ibc-core-host-types", - "ibc-core-router", - "ibc-core-router-types", - "ibc-primitives", -] - -[[package]] -name = "ibc-middleware-module" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=orm/v0.4.0#8d341de14ff5e2a637699796cffbf0fbbaee001f" -dependencies = [ - "ibc-core-channel-types", - "ibc-core-host-types", - "ibc-core-router", - "ibc-core-router-types", - "ibc-primitives", -] - -[[package]] -name = "ibc-middleware-module" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.9.0#3d3b436f7c58000c7498d68e88c15a955433a619" -dependencies = [ - "ibc-core-channel-types", - "ibc-core-host-types", - "ibc-core-router", - "ibc-core-router-types", - "ibc-primitives", -] - -[[package]] -name = "ibc-middleware-module-macros" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=module-macros/v0.1.0#3d3b436f7c58000c7498d68e88c15a955433a619" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "ibc-middleware-module-macros" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=orm/v0.4.0#8d341de14ff5e2a637699796cffbf0fbbaee001f" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "ibc-middleware-module-macros" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.9.0#3d3b436f7c58000c7498d68e88c15a955433a619" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "ibc-middleware-overflow-receive" -version = "0.4.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=orm/v0.4.0#8d341de14ff5e2a637699796cffbf0fbbaee001f" -dependencies = [ - "ibc-app-transfer-types", - "ibc-core-channel-types", - "ibc-core-host-types", - "ibc-core-router", - "ibc-core-router-types", - "ibc-middleware-module 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=orm/v0.4.0)", - "ibc-middleware-module-macros 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=orm/v0.4.0)", - "ibc-primitives", - "serde", - "serde_json", -] - [[package]] name = "ibc-middleware-packet-forward" -version = "0.9.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.9.0#3d3b436f7c58000c7498d68e88c15a955433a619" +version = "0.8.0" +source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.8.0#9c4a410063df8562c726c76009ff08b4e5a1894a" dependencies = [ "borsh", "dur", @@ -3882,8 +3802,6 @@ dependencies = [ "ibc-core-host-types", "ibc-core-router", "ibc-core-router-types", - "ibc-middleware-module 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.9.0)", - "ibc-middleware-module-macros 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.9.0)", "ibc-primitives", "serde", "serde_json", @@ -5276,9 +5194,6 @@ dependencies = [ "dur", "ibc", "ibc-derive", - "ibc-middleware-module 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=module/v0.1.0)", - "ibc-middleware-module-macros 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=module-macros/v0.1.0)", - "ibc-middleware-overflow-receive", "ibc-middleware-packet-forward", "ibc-testkit", "ics23", @@ -5506,7 +5421,6 @@ dependencies = [ "arbitrary", "assert_matches", "async-trait", - "bech32 0.8.1", "bimap", "borsh", "circular-queue", @@ -7036,9 +6950,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.38" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] diff --git a/Cargo.toml b/Cargo.toml index 0592ba7ab6..38a15f0d32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -121,10 +121,7 @@ git2 = { version = "0.18.1", default-features = false } # branch tiago/optional-ack ibc = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "38489943c4e75206eaffeeeec6153c039c2499d1", features = ["serde"] } ibc-derive = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "38489943c4e75206eaffeeeec6153c039c2499d1" } -ibc-middleware-module = { git = "https://github.com/heliaxdev/ibc-middleware", tag = "module/v0.1.0" } -ibc-middleware-module-macros = { git = "https://github.com/heliaxdev/ibc-middleware", tag = "module-macros/v0.1.0" } -ibc-middleware-overflow-receive = { git = "https://github.com/heliaxdev/ibc-middleware", tag = "orm/v0.4.0" } -ibc-middleware-packet-forward = { git = "https://github.com/heliaxdev/ibc-middleware", tag = "pfm/v0.9.0", features = ["borsh"] } +ibc-middleware-packet-forward = { git = "https://github.com/heliaxdev/ibc-middleware", tag = "pfm/v0.8.0", features = ["borsh"] } ibc-testkit = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "38489943c4e75206eaffeeeec6153c039c2499d1", default-features = false } ics23 = "0.12.0" usize-set = { version = "0.10.3", features = ["serialize-borsh", "serialize-serde"] } diff --git a/crates/apps/src/bin/namada/cli.rs b/crates/apps/src/bin/namada/cli.rs index bbe37d5959..f3165a4a41 100644 --- a/crates/apps/src/bin/namada/cli.rs +++ b/crates/apps/src/bin/namada/cli.rs @@ -50,7 +50,6 @@ fn handle_command(cmd: cli::cmds::Namada, raw_sub_cmd: String) -> Result<()> { | cli::cmds::Namada::TxShieldingTransfer(_) | cli::cmds::Namada::TxUnshieldingTransfer(_) | cli::cmds::Namada::TxIbcTransfer(_) - | cli::cmds::Namada::TxOsmosisSwap(_) | cli::cmds::Namada::TxUpdateAccount(_) | cli::cmds::Namada::TxRevealPk(_) | cli::cmds::Namada::TxInitProposal(_) diff --git a/crates/apps_lib/src/cli.rs b/crates/apps_lib/src/cli.rs index 6e715b86d5..ed74f4cf08 100644 --- a/crates/apps_lib/src/cli.rs +++ b/crates/apps_lib/src/cli.rs @@ -63,7 +63,6 @@ pub mod cmds { TxShieldingTransfer(TxShieldingTransfer), TxUnshieldingTransfer(TxUnshieldingTransfer), TxIbcTransfer(TxIbcTransfer), - TxOsmosisSwap(TxOsmosisSwap), TxUpdateAccount(TxUpdateAccount), TxInitProposal(TxInitProposal), TxVoteProposal(TxVoteProposal), @@ -85,7 +84,6 @@ pub mod cmds { .subcommand(TxShieldingTransfer::def().display_order(2)) .subcommand(TxUnshieldingTransfer::def().display_order(2)) .subcommand(TxIbcTransfer::def().display_order(2)) - .subcommand(TxOsmosisSwap::def().display_order(2)) .subcommand(TxUpdateAccount::def().display_order(2)) .subcommand(TxInitProposal::def().display_order(2)) .subcommand(TxVoteProposal::def().display_order(2)) @@ -109,8 +107,6 @@ pub mod cmds { SubCmd::parse(matches).map(Self::TxUnshieldingTransfer); let tx_ibc_transfer = SubCmd::parse(matches).map(Self::TxIbcTransfer); - let tx_osmosis_swap = - SubCmd::parse(matches).map(Self::TxOsmosisSwap); let tx_update_account = SubCmd::parse(matches).map(Self::TxUpdateAccount); let tx_init_proposal = @@ -128,7 +124,6 @@ pub mod cmds { .or(tx_shielding_transfer) .or(tx_unshielding_transfer) .or(tx_ibc_transfer) - .or(tx_osmosis_swap) .or(tx_update_account) .or(tx_init_proposal) .or(tx_vote_proposal) @@ -244,7 +239,6 @@ pub mod cmds { .subcommand(TxShieldingTransfer::def().display_order(1)) .subcommand(TxUnshieldingTransfer::def().display_order(1)) .subcommand(TxIbcTransfer::def().display_order(1)) - .subcommand(TxOsmosisSwap::def().display_order(1)) .subcommand(TxUpdateAccount::def().display_order(1)) .subcommand(TxInitAccount::def().display_order(1)) .subcommand(TxRevealPk::def().display_order(1)) @@ -320,7 +314,6 @@ pub mod cmds { let tx_unshielding_transfer = Self::parse_with_ctx(matches, TxUnshieldingTransfer); let tx_ibc_transfer = Self::parse_with_ctx(matches, TxIbcTransfer); - let tx_osmosis_swap = Self::parse_with_ctx(matches, TxOsmosisSwap); let tx_update_account = Self::parse_with_ctx(matches, TxUpdateAccount); let tx_init_account = Self::parse_with_ctx(matches, TxInitAccount); @@ -409,7 +402,6 @@ pub mod cmds { .or(tx_shielding_transfer) .or(tx_unshielding_transfer) .or(tx_ibc_transfer) - .or(tx_osmosis_swap) .or(tx_update_account) .or(tx_init_account) .or(tx_reveal_pk) @@ -504,7 +496,6 @@ pub mod cmds { TxShieldingTransfer(TxShieldingTransfer), TxUnshieldingTransfer(TxUnshieldingTransfer), TxIbcTransfer(TxIbcTransfer), - TxOsmosisSwap(TxOsmosisSwap), QueryResult(QueryResult), TxUpdateAccount(TxUpdateAccount), TxInitAccount(TxInitAccount), @@ -1416,25 +1407,6 @@ pub mod cmds { } } - #[derive(Clone, Debug)] - pub struct TxOsmosisSwap(pub args::TxOsmosisSwap); - - impl SubCmd for TxOsmosisSwap { - const CMD: &'static str = "osmosis-swap"; - - fn parse(matches: &ArgMatches) -> Option { - matches.subcommand_matches(Self::CMD).map(|matches| { - TxOsmosisSwap(args::TxOsmosisSwap::parse(matches)) - }) - } - - fn def() -> App { - App::new(Self::CMD) - .about(wrap!("Swap two asset kinds using Osmosis.")) - .add_args::>() - } - } - #[derive(Clone, Debug)] pub struct TxUpdateAccount(pub args::TxUpdateAccount); @@ -3384,7 +3356,6 @@ pub mod args { use crate::wrap; pub const ADDRESS: Arg = arg("address"); - pub const ADDRESS_OPT: ArgOpt = arg_opt("address"); pub const ADD_PERSISTENT_PEERS: ArgFlag = flag("add-persistent-peers"); pub const ALIAS_OPT: ArgOpt = ALIAS.opt(); pub const ALIAS: Arg = arg("alias"); @@ -3537,7 +3508,6 @@ pub mod args { pub const LIST_FIND_ADDRESSES_ONLY: ArgFlag = flag("addr"); pub const LIST_FIND_KEYS_ONLY: ArgFlag = flag("keys"); pub const LOCALHOST: ArgFlag = flag("localhost"); - pub const LOCAL_RECOVERY_ADDR: Arg = arg("local-recovery-addr"); pub const MASP_EPOCH: ArgOpt = arg_opt("masp-epoch"); pub const MAX_COMMISSION_RATE_CHANGE: Arg = arg("max-commission-rate-change"); @@ -3546,30 +3516,21 @@ pub mod args { pub const MAX_ETH_GAS: ArgOpt = arg_opt("max_eth-gas"); pub const MEMO_OPT: ArgOpt = arg_opt("memo"); pub const MIGRATION_PATH: ArgOpt = arg_opt("migration-path"); - pub const MINIMUM_AMOUNT: ArgOpt = - arg_opt("minimum-amount"); pub const MODE: ArgOpt = arg_opt("mode"); pub const NET_ADDRESS: Arg = arg("net-address"); pub const NAMADA_START_TIME: ArgOpt = arg_opt("time"); pub const NO_CONVERSIONS: ArgFlag = flag("no-conversions"); pub const NO_EXPIRATION: ArgFlag = flag("no-expiration"); pub const NUT: ArgFlag = flag("nut"); - pub const OSMOSIS_REST_RPC: Arg = arg("osmosis-rest-rpc"); pub const OUT_FILE_PATH_OPT: ArgOpt = arg_opt("out-file-path"); pub const OUTPUT: ArgOpt = arg_opt("output"); - pub const OUTPUT_DENOM: Arg = arg("output-denom"); pub const OUTPUT_FOLDER_PATH: ArgOpt = arg_opt("output-folder-path"); - pub const OSMOSIS_POOL_HOP: ArgMulti = - arg_multi("pool-hop"); - pub const OVERFLOW_OPT: ArgOpt = arg_opt("overflow-addr"); pub const OWNER: Arg = arg("owner"); pub const OWNER_OPT: ArgOpt = OWNER.opt(); pub const PATH: Arg = arg("path"); pub const PATH_OPT: ArgOpt = arg_opt("path"); pub const PAYMENT_ADDRESS_TARGET: Arg = arg("target"); - pub const PAYMENT_ADDRESS_TARGET_OPT: ArgOpt = - arg_opt("target-pa"); pub const PORT_ID: ArgDefault = arg_default( "port-id", DefaultFn(|| PortId::from_str("transfer").unwrap()), @@ -3617,7 +3578,6 @@ pub mod args { pub const SHIELDED: ArgFlag = flag("shielded"); pub const SHOW_IBC_TOKENS: ArgFlag = flag("show-ibc-tokens"); pub const SIGNER: ArgOpt = arg_opt("signer"); - pub const SLIPPAGE: ArgOpt = arg_opt("slippage-percentage"); pub const SIGNING_KEYS: ArgMulti = arg_multi("signing-keys"); pub const SIGNATURES: ArgMulti = arg_multi("signatures"); @@ -3631,7 +3591,6 @@ pub mod args { pub const STORAGE_KEY: Arg = arg("storage-key"); pub const SUSPEND_ACTION: ArgFlag = flag("suspend"); pub const TARGET: Arg = arg("target"); - pub const TARGET_OPT: ArgOpt = arg_opt("target"); pub const TEMPLATES_PATH: Arg = arg("templates-path"); pub const TIMEOUT_HEIGHT: ArgOpt = arg_opt("timeout-height"); pub const TIMEOUT_SEC_OFFSET: ArgOpt = arg_opt("timeout-sec-offset"); @@ -3675,7 +3634,6 @@ pub mod args { pub const WASM_CHECKSUMS_PATH: Arg = arg("wasm-checksums-path"); pub const WASM_DIR: ArgOpt = arg_opt("wasm-dir"); pub const WEBSITE_OPT: ArgOpt = arg_opt("website"); - pub const WINDOW_SECONDS: ArgOpt = arg_opt("window-seconds"); pub const WITH_INDEXER: ArgOpt = arg_opt("with-indexer"); pub const WRAPPER_SIGNATURE_OPT: ArgOpt = arg_opt("gas-signature"); pub const TX_PATH: Arg = arg("tx-path"); @@ -5070,184 +5028,6 @@ pub mod args { } } - impl CliToSdk> for TxOsmosisSwap { - type Error = std::io::Error; - - fn to_sdk( - self, - ctx: &mut Context, - ) -> Result, Self::Error> { - let chain_ctx = ctx.borrow_mut_chain_or_exit(); - let recipient = match self.recipient { - Either::Left(r) => Either::Left(chain_ctx.get(&r)), - Either::Right(r) => Either::Right(chain_ctx.get(&r)), - }; - let overflow = self.overflow.map(|r| chain_ctx.get(&r)); - Ok(TxOsmosisSwap { - transfer: self.transfer.to_sdk(ctx)?, - output_denom: self.output_denom, - recipient, - overflow, - slippage: self.slippage, - local_recovery_addr: self.local_recovery_addr, - route: self.route, - osmosis_rest_rpc: self.osmosis_rest_rpc, - }) - } - } - - impl Args for TxOsmosisSwap { - fn parse(matches: &ArgMatches) -> Self { - let transfer = TxIbcTransfer::parse(matches); - let osmosis_rest_rpc = OSMOSIS_REST_RPC.parse(matches); - let output_denom = OUTPUT_DENOM.parse(matches); - let maybe_trans_recipient = TARGET_OPT.parse(matches); - let maybe_shielded_recipient = - PAYMENT_ADDRESS_TARGET_OPT.parse(matches); - let maybe_overflow = OVERFLOW_OPT.parse(matches); - let slippage_percent = SLIPPAGE.parse(matches); - if slippage_percent - .is_some_and(|percent| !(0.0..=100.0).contains(&percent)) - { - panic!( - "The slippage percent must be a number between 0 and 100." - ) - } - let window_seconds = WINDOW_SECONDS.parse(matches); - let minimum_amount = MINIMUM_AMOUNT.parse(matches); - let slippage = minimum_amount - .map(|d| Slippage::MinOutputAmount(d.redenominate(0).amount())) - .or_else(|| { - Some(Slippage::Twap { - slippage_percentage: slippage_percent - .expect( - "If a minimum amount was not provided, \ - slippage-percentage and window-seconds must \ - be specified.", - ) - .to_string(), - window_seconds: window_seconds.expect( - "If a minimum amount was not provided, \ - slippage-percentage and window-seconds must be \ - specified.", - ), - }) - }) - .unwrap(); - let local_recovery_addr = LOCAL_RECOVERY_ADDR.parse(matches); - let route = match OSMOSIS_POOL_HOP.parse(matches) { - r if r.is_empty() => None, - r => Some(r), - }; - Self { - transfer, - output_denom, - recipient: if let Some(target) = maybe_trans_recipient { - Either::Left(target) - } else { - Either::Right(maybe_shielded_recipient.unwrap()) - }, - overflow: maybe_overflow, - slippage, - local_recovery_addr, - route, - osmosis_rest_rpc, - } - } - - fn def(app: App) -> App { - app.add_args::>() - .arg( - OSMOSIS_REST_RPC - .def() - .help(wrap!("A url pointing to an Osmosis REST rpc.")), - ) - .arg(OSMOSIS_POOL_HOP.def().help(wrap!( - "Individual hop of the route to take through Osmosis \ - pools. This value takes the form \ - :. When unspecified, \ - the optimal route is queried on the fly." - ))) - .arg(OUTPUT_DENOM.def().help(wrap!( - "IBC trace path (on Namada) of the desired asset. This is \ - a string of the form \ - `transfer//`, where `` \ - is the channel that connects Namada to some counterparty \ - chain." - ))) - .arg( - TARGET_OPT - .def() - .conflicts_with(OVERFLOW_OPT.name) - .conflicts_with(PAYMENT_ADDRESS_TARGET_OPT.name) - .help(wrap!( - "Transparent Namada address that shall receive \ - the swapped tokens." - )), - ) - .arg( - PAYMENT_ADDRESS_TARGET_OPT - .def() - .conflicts_with(TARGET_OPT.name) - .help(wrap!( - "Namada payment address that shall receive the \ - minimum amount of tokens swapped on Osmosis." - )), - ) - .arg(OVERFLOW_OPT.def().help(wrap!( - "Transparent address that receives the amount of target \ - asset exceeding the minimum trade amount. Only \ - applicable when shielding assets that have been swapped \ - on Osmosis. This address should not be linkable to any \ - of the user's personal accounts, to maximize the privacy \ - of the trade. If unspecified, a disposable address is \ - generated." - ))) - .arg(SLIPPAGE.def().requires(WINDOW_SECONDS.name).help(wrap!( - "Slippage percentage, as a number between 0 and 100. \ - Represents the maximum acceptable deviation from the \ - expected price during a trade." - ))) - .arg(WINDOW_SECONDS.def().requires(SLIPPAGE.name).help(wrap!( - "Time period (in seconds) over which the average price is \ - calculated." - ))) - .arg( - MINIMUM_AMOUNT - .def() - .conflicts_with(SLIPPAGE.name) - .conflicts_with(WINDOW_SECONDS.name) - .help(wrap!( - "Minimum amount of target asset that the trade \ - should produce." - )), - ) - .arg(LOCAL_RECOVERY_ADDR.def().help(wrap!( - "Address on Osmosis from which to recover funds in case \ - of failure." - ))) - .group( - ArgGroup::new("slippage") - .args([SLIPPAGE.name, MINIMUM_AMOUNT.name]) - .required(true), - ) - .group( - ArgGroup::new("transfer-target") - .args([ - TARGET_OPT.name, - PAYMENT_ADDRESS_TARGET_OPT.name, - ]) - .required(true), - ) - .mut_arg(RECEIVER.name, |arg| { - arg.long("swap-contract").help(wrap!( - "Address of the Osmosis contract performing the swap. \ - It will be the receiver of the IBC transfer." - )) - }) - } - } - impl CliToSdk> for TxInitAccount { type Error = std::io::Error; @@ -7077,22 +6857,11 @@ pub mod args { query, output_folder: self.output_folder, target: chain_ctx.get(&self.target), + token: self.token, amount: self.amount, expiration: self.expiration, - asset: match self.asset { - IbcShieldingTransferAsset::LookupNamadaAddress { - port_id, - channel_id, - token, - } => IbcShieldingTransferAsset::LookupNamadaAddress { - port_id, - channel_id, - token, - }, - IbcShieldingTransferAsset::Address(addr) => { - IbcShieldingTransferAsset::Address(chain_ctx.get(&addr)) - } - }, + port_id: self.port_id, + channel_id: self.channel_id, }) } } @@ -7121,13 +6890,11 @@ pub mod args { query, output_folder, target, + token, amount, expiration, - asset: IbcShieldingTransferAsset::LookupNamadaAddress { - port_id, - channel_id, - token, - }, + port_id, + channel_id, } } diff --git a/crates/apps_lib/src/cli/client.rs b/crates/apps_lib/src/cli/client.rs index 7899bdcc5d..d926671e17 100644 --- a/crates/apps_lib/src/cli/client.rs +++ b/crates/apps_lib/src/cli/client.rs @@ -113,21 +113,6 @@ impl CliApi { let namada = ctx.to_sdk(client, io); tx::submit_ibc_transfer(&namada, args).await?; } - Sub::TxOsmosisSwap(TxOsmosisSwap(args)) => { - let chain_ctx = ctx.borrow_mut_chain_or_exit(); - let ledger_address = - chain_ctx.get(&args.transfer.tx.ledger_address); - let client = client.unwrap_or_else(|| { - C::from_tendermint_address(&ledger_address) - }); - client.wait_until_node_is_synced(&io).await?; - - let args = args.to_sdk(&mut ctx)?; - let namada = ctx.to_sdk(client, io); - let args = args.into_ibc_transfer(&namada).await?; - - tx::submit_ibc_transfer(&namada, args).await?; - } Sub::TxUpdateAccount(TxUpdateAccount(args)) => { let chain_ctx = ctx.borrow_mut_chain_or_exit(); let ledger_address = diff --git a/crates/apps_lib/src/client/tx.rs b/crates/apps_lib/src/client/tx.rs index a2f8b03037..f954e43dc4 100644 --- a/crates/apps_lib/src/client/tx.rs +++ b/crates/apps_lib/src/client/tx.rs @@ -1909,13 +1909,12 @@ pub async fn gen_ibc_shielding_transfer( context: &impl Namada, args: args::GenIbcShieldingTransfer, ) -> Result<(), error::Error> { - let output_folder = args.output_folder.clone(); - - if let Some(masp_tx) = tx::gen_ibc_shielding_transfer(context, args).await? + if let Some(masp_tx) = + tx::gen_ibc_shielding_transfer(context, args.clone()).await? { let tx_id = masp_tx.txid().to_string(); let filename = format!("ibc_masp_tx_{}.memo", tx_id); - let output_path = match output_folder { + let output_path = match &args.output_folder { Some(path) => path.join(filename), None => filename.into(), }; diff --git a/crates/core/src/address.rs b/crates/core/src/address.rs index 962b40d66c..0590c695eb 100644 --- a/crates/core/src/address.rs +++ b/crates/core/src/address.rs @@ -393,18 +393,6 @@ impl Debug for Address { } } -impl From<&Address> for Signer { - fn from(address: &Address) -> Signer { - address.to_string().into() - } -} - -impl From
for Signer { - fn from(address: Address) -> Signer { - (&address).into() - } -} - impl TryFrom<&Signer> for Address { type Error = DecodeError; diff --git a/crates/core/src/token.rs b/crates/core/src/token.rs index 09028217f9..7b1b4b8d62 100644 --- a/crates/core/src/token.rs +++ b/crates/core/src/token.rs @@ -534,15 +534,6 @@ impl DenominatedAmount { .ok_or(AmountParseError::PrecisionOverflow) } - /// Create a new [`DenominatedAmount`] with the same underlying - /// amout but a new denomination. - pub fn redenominate(self, new_denom: u8) -> Self { - Self { - amount: self.amount, - denom: new_denom.into(), - } - } - /// Multiply this number by 10^denom and return the computed integer if /// possible. Otherwise error out. pub fn scale( diff --git a/crates/ibc/Cargo.toml b/crates/ibc/Cargo.toml index c6f2be9004..f520e810c3 100644 --- a/crates/ibc/Cargo.toml +++ b/crates/ibc/Cargo.toml @@ -45,9 +45,6 @@ konst.workspace = true linkme = {workspace = true, optional = true} ibc.workspace = true ibc-derive.workspace = true -ibc-middleware-module.workspace = true -ibc-middleware-module-macros.workspace = true -ibc-middleware-overflow-receive.workspace = true ibc-middleware-packet-forward.workspace = true ibc-testkit = {workspace = true, optional = true} ics23.workspace = true diff --git a/crates/ibc/src/context/middlewares.rs b/crates/ibc/src/context/middlewares.rs index d563071bde..8d65666e63 100644 --- a/crates/ibc/src/context/middlewares.rs +++ b/crates/ibc/src/context/middlewares.rs @@ -1,7 +1,7 @@ //! Middleware entry points on Namada. pub mod pfm_mod; -pub mod shielded_recv; +// mod crossroads_mod; use std::cell::RefCell; use std::collections::BTreeSet; @@ -12,18 +12,16 @@ use std::rc::Rc; use ibc::core::host::types::identifiers::PortId; use ibc::core::router::module::Module; use ibc::core::router::types::module::ModuleId; -use ibc_middleware_overflow_receive::OverflowReceiveMiddleware; -use ibc_middleware_packet_forward::PacketForwardMiddleware; +use ibc_middleware_packet_forward::{PacketForwardMiddleware, PfmContext}; use namada_core::address::Address; use self::pfm_mod::PfmTransferModule; -use self::shielded_recv::ShieldedRecvModule; use crate::context::transfer_mod::TransferModule; use crate::{IbcCommonContext, IbcStorageContext}; /// The stack of middlewares of the transfer module. pub type TransferMiddlewares = - OverflowReceiveMiddleware>; + PacketForwardMiddleware>; /// Create a new instance of [`TransferMiddlewares`] pub fn create_transfer_middlewares( @@ -34,18 +32,16 @@ where C: IbcCommonContext + Debug, Params: namada_systems::parameters::Read<::Storage>, { - OverflowReceiveMiddleware::wrap(ShieldedRecvModule { - next: PacketForwardMiddleware::wrap(PfmTransferModule { - transfer_module: TransferModule::new(ctx, verifiers), - _phantom: PhantomData, - }), + PacketForwardMiddleware::wrap(PfmTransferModule { + transfer_module: TransferModule::new(ctx, verifiers), + _phantom: PhantomData, }) } impl crate::ModuleWrapper for TransferMiddlewares where C: IbcCommonContext + Debug, - Params: namada_systems::parameters::Read<::Storage>, + PfmTransferModule: PfmContext, { fn as_module(&self) -> &dyn Module { self diff --git a/crates/ibc/src/context/middlewares/pfm_mod.rs b/crates/ibc/src/context/middlewares/pfm_mod.rs index f414695a5f..70454fbf4a 100644 --- a/crates/ibc/src/context/middlewares/pfm_mod.rs +++ b/crates/ibc/src/context/middlewares/pfm_mod.rs @@ -26,8 +26,6 @@ use ibc::core::host::types::identifiers::{ use ibc::core::router::module::Module; use ibc::core::router::types::module::ModuleExtras; use ibc::primitives::Signer; -use ibc_middleware_module::MiddlewareModule; -use ibc_middleware_module_macros::from_middleware; use ibc_middleware_packet_forward::{ InFlightPacket, InFlightPacketKey, PfmContext, }; @@ -62,27 +60,167 @@ impl Debug } } -from_middleware! { - impl Module for PfmTransferModule - where - C: IbcCommonContext + Debug, -} - -impl MiddlewareModule for PfmTransferModule +impl Module for PfmTransferModule where C: IbcCommonContext + Debug, { - type NextMiddleware = TransferModule; + fn on_chan_open_init_validate( + &self, + order: Order, + connection_hops: &[ConnectionId], + port_id: &PortId, + channel_id: &ChannelId, + counterparty: &Counterparty, + version: &Version, + ) -> Result { + self.transfer_module.on_chan_open_init_validate( + order, + connection_hops, + port_id, + channel_id, + counterparty, + version, + ) + } + + fn on_chan_open_init_execute( + &mut self, + order: Order, + connection_hops: &[ConnectionId], + port_id: &PortId, + channel_id: &ChannelId, + counterparty: &Counterparty, + version: &Version, + ) -> Result<(ModuleExtras, Version), ChannelError> { + self.transfer_module.on_chan_open_init_execute( + order, + connection_hops, + port_id, + channel_id, + counterparty, + version, + ) + } + + fn on_chan_open_try_validate( + &self, + order: Order, + connection_hops: &[ConnectionId], + port_id: &PortId, + channel_id: &ChannelId, + counterparty: &Counterparty, + counterparty_version: &Version, + ) -> Result { + self.transfer_module.on_chan_open_try_validate( + order, + connection_hops, + port_id, + channel_id, + counterparty, + counterparty_version, + ) + } + + fn on_chan_open_try_execute( + &mut self, + order: Order, + connection_hops: &[ConnectionId], + port_id: &PortId, + channel_id: &ChannelId, + counterparty: &Counterparty, + counterparty_version: &Version, + ) -> Result<(ModuleExtras, Version), ChannelError> { + self.transfer_module.on_chan_open_try_execute( + order, + connection_hops, + port_id, + channel_id, + counterparty, + counterparty_version, + ) + } + + fn on_chan_open_ack_validate( + &self, + port_id: &PortId, + channel_id: &ChannelId, + counterparty_version: &Version, + ) -> Result<(), ChannelError> { + self.transfer_module.on_chan_open_ack_validate( + port_id, + channel_id, + counterparty_version, + ) + } + + fn on_chan_open_ack_execute( + &mut self, + port_id: &PortId, + channel_id: &ChannelId, + counterparty_version: &Version, + ) -> Result { + self.transfer_module.on_chan_open_ack_execute( + port_id, + channel_id, + counterparty_version, + ) + } + + fn on_chan_open_confirm_validate( + &self, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result<(), ChannelError> { + self.transfer_module + .on_chan_open_confirm_validate(port_id, channel_id) + } - fn next_middleware(&self) -> &Self::NextMiddleware { - &self.transfer_module + fn on_chan_open_confirm_execute( + &mut self, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result { + self.transfer_module + .on_chan_open_confirm_execute(port_id, channel_id) } - fn next_middleware_mut(&mut self) -> &mut Self::NextMiddleware { - &mut self.transfer_module + fn on_chan_close_init_validate( + &self, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result<(), ChannelError> { + self.transfer_module + .on_chan_close_init_validate(port_id, channel_id) } - fn middleware_on_recv_packet_execute( + fn on_chan_close_init_execute( + &mut self, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result { + self.transfer_module + .on_chan_close_init_execute(port_id, channel_id) + } + + fn on_chan_close_confirm_validate( + &self, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result<(), ChannelError> { + self.transfer_module + .on_chan_close_confirm_validate(port_id, channel_id) + } + + fn on_chan_close_confirm_execute( + &mut self, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result { + self.transfer_module + .on_chan_close_confirm_execute(port_id, channel_id) + } + + fn on_recv_packet_execute( &mut self, packet: &Packet, relayer: &Signer, @@ -105,6 +243,50 @@ where self.transfer_module.on_recv_packet_execute(packet, relayer) } } + + fn on_acknowledgement_packet_validate( + &self, + packet: &Packet, + acknowledgement: &Acknowledgement, + relayer: &Signer, + ) -> Result<(), PacketError> { + self.transfer_module.on_acknowledgement_packet_validate( + packet, + acknowledgement, + relayer, + ) + } + + fn on_acknowledgement_packet_execute( + &mut self, + packet: &Packet, + acknowledgement: &Acknowledgement, + relayer: &Signer, + ) -> (ModuleExtras, Result<(), PacketError>) { + self.transfer_module.on_acknowledgement_packet_execute( + packet, + acknowledgement, + relayer, + ) + } + + fn on_timeout_packet_validate( + &self, + packet: &Packet, + relayer: &Signer, + ) -> Result<(), PacketError> { + self.transfer_module + .on_timeout_packet_validate(packet, relayer) + } + + fn on_timeout_packet_execute( + &mut self, + packet: &Packet, + relayer: &Signer, + ) -> (ModuleExtras, Result<(), PacketError>) { + self.transfer_module + .on_timeout_packet_execute(packet, relayer) + } } impl PfmContext for PfmTransferModule diff --git a/crates/ibc/src/context/middlewares/shielded_recv.rs b/crates/ibc/src/context/middlewares/shielded_recv.rs deleted file mode 100644 index 56aa5d42d0..0000000000 --- a/crates/ibc/src/context/middlewares/shielded_recv.rs +++ /dev/null @@ -1,213 +0,0 @@ -//! This middleware is to handle automatically shielding the results of a -//! shielded swap. -//! -//! Since we do not know the resulting amount of assets from the swap ahead of -//! time, we cannot create a MASP note at the onset. We instead, create a note -//! for the minimum amount, which will be shielded. All assets exceeding the -//! minimum amount will be transferred to an overflow address specified by -//! the user. - -use std::cell::RefCell; -use std::collections::BTreeSet; -use std::fmt::{Debug, Formatter}; -use std::rc::Rc; - -use ibc::apps::transfer::context::TokenTransferExecutionContext; -use ibc::apps::transfer::types::packet::PacketData; -use ibc::apps::transfer::types::{Coin, PrefixedDenom}; -use ibc::core::channel::types::acknowledgement::{ - Acknowledgement, AcknowledgementStatus, StatusValue as AckStatusValue, -}; -use ibc::core::channel::types::channel::{Counterparty, Order}; -use ibc::core::channel::types::error::{ChannelError, PacketError}; -use ibc::core::channel::types::packet::Packet; -use ibc::core::channel::types::Version; -use ibc::core::host::types::identifiers::{ChannelId, ConnectionId, PortId}; -use ibc::core::router::module::Module; -use ibc::core::router::types::module::ModuleExtras; -use ibc::primitives::Signer; -use ibc_middleware_module::MiddlewareModule; -use ibc_middleware_module_macros::from_middleware; -use ibc_middleware_overflow_receive::OverflowRecvContext; -use ibc_middleware_packet_forward::PacketForwardMiddleware; -use namada_core::address::{Address, MASP, MULTITOKEN}; -use namada_core::token; -use serde_json::{Map, Value}; - -use crate::context::middlewares::pfm_mod::PfmTransferModule; -use crate::msg::{NamadaMemo, OsmosisSwapMemoData}; -use crate::{Error, IbcCommonContext, IbcStorageContext, TokenTransferContext}; - -/// A middleware for handling IBC pockets received -/// after a shielded swap. The minimum amount will -/// be shielded and the rest placed in an overflow -/// account. -pub struct ShieldedRecvModule -where - C: IbcCommonContext + Debug, - Params: namada_systems::parameters::Read<::Storage>, -{ - /// The next middleware module - pub next: PacketForwardMiddleware>, -} - -impl ShieldedRecvModule -where - C: IbcCommonContext + Debug, - Params: namada_systems::parameters::Read<::Storage>, -{ - fn insert_verifier(&self, address: Address) { - self.next - .next() - .transfer_module - .ctx - .verifiers - .borrow_mut() - .insert(address); - } - - fn get_ctx(&self) -> Rc> { - self.next.next().transfer_module.ctx.inner.clone() - } - - fn get_verifiers(&self) -> Rc>> { - self.next.next().transfer_module.ctx.verifiers.clone() - } -} - -impl Debug for ShieldedRecvModule -where - C: IbcCommonContext + Debug, - Params: namada_systems::parameters::Read<::Storage>, -{ - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct(stringify!(ShieldedRecvModule)) - .field("next", &self.next) - .finish() - } -} - -from_middleware! { - impl Module for ShieldedRecvModule - where - C: IbcCommonContext + Debug, - Params: namada_systems::parameters::Read<::Storage>, -} - -impl MiddlewareModule for ShieldedRecvModule -where - C: IbcCommonContext + Debug, - Params: namada_systems::parameters::Read<::Storage>, -{ - type NextMiddleware = PacketForwardMiddleware>; - - fn next_middleware(&self) -> &Self::NextMiddleware { - &self.next - } - - fn next_middleware_mut(&mut self) -> &mut Self::NextMiddleware { - &mut self.next - } - - fn middleware_on_recv_packet_execute( - &mut self, - packet: &Packet, - relayer: &Signer, - ) -> (ModuleExtras, Option) { - let Ok(data) = serde_json::from_slice::(&packet.data) - else { - // NB: this isn't an ICS-20 packet - return self.next.on_recv_packet_execute(packet, relayer); - }; - let Ok(memo) = serde_json::from_str::>( - data.memo.as_ref(), - ) else { - // NB: this isn't a shielded recv packet - return self.next.on_recv_packet_execute(packet, relayer); - }; - - if data.receiver.as_ref() != MASP.to_string() { - let ack = AcknowledgementStatus::error( - AckStatusValue::new(format!( - "Shielded receive error: Address {:?} is not the MASP", - data.receiver.as_ref() - )) - .expect("Ack is not empty"), - ); - return (ModuleExtras::empty(), Some(ack.into())); - } - - self.insert_verifier(memo.namada.osmosis_swap.overflow_receiver); - self.insert_verifier(MULTITOKEN); - - self.next.on_recv_packet_execute(packet, relayer) - } -} - -impl ibc_middleware_overflow_receive::PacketMetadata - for NamadaMemo -{ - type AccountId = Address; - type Amount = token::Amount; - - fn is_overflow_receive_msg(msg: &Map) -> bool { - msg.get("namada").map_or(false, |maybe_namada_obj| { - maybe_namada_obj - .as_object() - .map_or(false, |namada| namada.contains_key("osmosis_swap")) - }) - } - - fn strip_middleware_msg( - json_obj_memo: Map, - ) -> Map { - json_obj_memo - } - - fn overflow_receiver(&self) -> &Address { - &self.namada.osmosis_swap.overflow_receiver - } - - fn target_amount(&self) -> &token::Amount { - &self.namada.osmosis_swap.shielded_amount - } -} - -impl OverflowRecvContext for ShieldedRecvModule -where - C: IbcCommonContext + Debug, - Params: namada_systems::parameters::Read<::Storage>, -{ - type Error = Error; - type PacketMetadata = NamadaMemo; - - fn mint_coins_execute( - &mut self, - receiver: &Address, - coin: &Coin, - ) -> Result<(), Self::Error> { - let ctx = self.get_ctx(); - let verifiers = self.get_verifiers(); - let mut token_transfer_context = - TokenTransferContext::new(ctx, verifiers); - token_transfer_context - .mint_coins_execute(receiver, coin) - .map_err(Error::TokenTransfer) - } - - fn unescrow_coins_execute( - &mut self, - receiver: &Address, - port: &PortId, - channel: &ChannelId, - coin: &Coin, - ) -> Result<(), Self::Error> { - let ctx = self.get_ctx(); - let verifiers = self.get_verifiers(); - let mut token_transfer_context = - TokenTransferContext::new(ctx, verifiers); - token_transfer_context - .unescrow_coins_execute(receiver, port, channel, coin) - .map_err(Error::TokenTransfer) - } -} diff --git a/crates/ibc/src/lib.rs b/crates/ibc/src/lib.rs index ea03869024..69a064dcb6 100644 --- a/crates/ibc/src/lib.rs +++ b/crates/ibc/src/lib.rs @@ -617,7 +617,7 @@ where tx_data: &[u8], ) -> Result<(Option, Option), Error> { let message = decode_message::(tx_data)?; - let result = match message { + match message { IbcMessage::Transfer(msg) => { let mut token_transfer_ctx = TokenTransferContext::new( self.ctx.inner.clone(), @@ -635,6 +635,7 @@ where )) })?, ); + self.insert_verifiers()?; if msg.transfer.is_some() { token_transfer_ctx.enable_shielded_transfer(); } @@ -664,6 +665,7 @@ where )) })?, ); + self.insert_verifiers()?; send_nft_transfer_execute( &mut self.ctx, &mut nft_transfer_ctx, @@ -683,6 +685,7 @@ where )) })?, ); + self.insert_verifiers()?; } execute(&mut self.ctx, &mut self.router, *envelope.clone()) .map_err(|e| Error::Context(Box::new(e)))?; @@ -707,9 +710,7 @@ where }; Ok((None, masp_tx)) } - }; - self.insert_verifiers()?; - result + } } /// Check the result of receiving the packet by checking the packet @@ -747,12 +748,13 @@ where let verifiers = Rc::new(RefCell::new(BTreeSet::
::new())); let message = decode_message::(tx_data)?; - let result = match message { + match message { IbcMessage::Transfer(msg) => { let mut token_transfer_ctx = TokenTransferContext::new( self.ctx.inner.clone(), verifiers.clone(), ); + self.insert_verifiers()?; if msg.transfer.is_some() { token_transfer_ctx.enable_shielded_transfer(); } @@ -780,9 +782,7 @@ where validate(&self.ctx, &self.router, *envelope) .map_err(|e| Error::Context(Box::new(e))) } - }; - self.insert_verifiers()?; - result + } } fn insert_verifiers(&self) -> Result<(), Error> { diff --git a/crates/ibc/src/msg.rs b/crates/ibc/src/msg.rs index c5d75407df..8a15817c00 100644 --- a/crates/ibc/src/msg.rs +++ b/crates/ibc/src/msg.rs @@ -1,6 +1,4 @@ use std::collections::BTreeMap; -use std::fmt; -use std::str::FromStr; use borsh::schema::{Declaration, Definition, Fields}; use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; @@ -18,106 +16,6 @@ use ibc::core::host::types::identifiers::PortId; use ibc::primitives::proto::Protobuf; use masp_primitives::transaction::Transaction as MaspTransaction; use namada_core::borsh::BorshSerializeExt; -use namada_core::string_encoding::StringEncoded; -use serde::{Deserialize, Serialize}; - -trait Sealed {} - -/// Marker trait that denotes whether an IBC memo is valid -/// in Namada. -#[allow(private_bounds)] -pub trait ValidNamadaMemo: Sealed {} - -impl Sealed for NamadaMemo {} -impl ValidNamadaMemo for NamadaMemo {} - -impl Sealed for NamadaMemo {} -impl ValidNamadaMemo for NamadaMemo {} - -/// Osmosis swap memo data. -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub struct OsmosisSwapMemoData { - /// The inner memo data. - pub osmosis_swap: OsmosisSwapMemoDataInner, -} - -/// Osmosis swap inner memo data. -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub struct OsmosisSwapMemoDataInner { - /// Shielding transfer data. Hex encodes the borsh serialized MASP - /// transfer. - pub shielding_data: StringEncoded, - /// The amount that is shielded onto the MASP. Corresponds to the - /// minimum output amount from the swap. - pub shielded_amount: namada_core::token::Amount, - /// The receiver of the difference between the transferred tokens and - /// the minimum output amount. - pub overflow_receiver: namada_core::address::Address, -} - -impl From> for NamadaMemo { - fn from(memo: NamadaMemo) -> Self { - memo.namada.into() - } -} - -impl From for NamadaMemo { - fn from( - OsmosisSwapMemoData { - osmosis_swap: - OsmosisSwapMemoDataInner { - shielding_data, - shielded_amount, - overflow_receiver, - }, - }: OsmosisSwapMemoData, - ) -> Self { - Self { - namada: NamadaMemoData::OsmosisSwap { - overflow_receiver, - shielded_amount, - shielding_data, - }, - } - } -} - -impl From for NamadaMemo { - fn from(data: OsmosisSwapMemoData) -> Self { - Self { namada: data } - } -} - -/// Memo data serialized as a JSON object included -/// in IBC packets. -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub struct NamadaMemo { - /// The inner memo data. - pub namada: Data, -} - -/// Data included in a Namada memo. -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum NamadaMemoData { - /// Generic message sent over IBC. - Memo(String), - /// Osmosis swap message. - OsmosisSwap { - /// Shielding transfer data. Hex encodes the borsh serialized MASP - /// transfer. - shielding_data: StringEncoded, - /// The amount that is shielded onto the MASP. Corresponds to the - /// minimum output amount from the swap. - shielded_amount: namada_core::token::Amount, - /// The receiver of the difference between the transferred tokens and - /// the minimum output amount. - overflow_receiver: namada_core::address::Address, - }, -} /// The different variants of an Ibc message #[derive(Debug, Clone)] @@ -234,32 +132,9 @@ impl BorshSchema for MsgNftTransfer { #[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] pub struct IbcShieldingData(pub MaspTransaction); -impl From<&IbcShieldingData> for String { - fn from(data: &IbcShieldingData) -> Self { - HEXUPPER.encode(&data.serialize_to_vec()) - } -} - impl From for String { fn from(data: IbcShieldingData) -> Self { - (&data).into() - } -} - -impl fmt::Display for IbcShieldingData { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", String::from(self)) - } -} - -impl FromStr for IbcShieldingData { - type Err = String; - - fn from_str(s: &str) -> Result { - let bytes = HEXUPPER - .decode(s.as_bytes()) - .map_err(|err| err.to_string())?; - IbcShieldingData::try_from_slice(&bytes).map_err(|err| err.to_string()) + HEXUPPER.encode(&data.serialize_to_vec()) } } @@ -279,17 +154,8 @@ pub fn extract_masp_tx_from_envelope( pub fn decode_ibc_shielding_data( s: impl AsRef, ) -> Option { - let sref = s.as_ref(); - - serde_json::from_str(sref).map_or_else( - |_| sref.parse().ok(), - |NamadaMemo { namada: memo_data }| match memo_data { - NamadaMemoData::Memo(memo) => memo.parse().ok(), - NamadaMemoData::OsmosisSwap { shielding_data, .. } => { - Some(shielding_data.raw) - } - }, - ) + let bytes = HEXUPPER.decode(s.as_ref().as_bytes()).ok()?; + IbcShieldingData::try_from_slice(&bytes).ok() } /// Extract MASP transaction from IBC packet memo diff --git a/crates/sdk/Cargo.toml b/crates/sdk/Cargo.toml index f81e052373..517a0baaa1 100644 --- a/crates/sdk/Cargo.toml +++ b/crates/sdk/Cargo.toml @@ -91,7 +91,6 @@ namada_wallet = {path = "../wallet" } arbitrary = { workspace = true, optional = true } async-trait.workspace = true -bech32.workspace = true bimap.workspace = true borsh.workspace = true circular-queue.workspace = true diff --git a/crates/sdk/src/args.rs b/crates/sdk/src/args.rs index 24168c7b78..84274231ff 100644 --- a/crates/sdk/src/args.rs +++ b/crates/sdk/src/args.rs @@ -8,7 +8,7 @@ use std::time::Duration as StdDuration; use either::Either; use masp_primitives::transaction::components::sapling::builder::BuildParams; use masp_primitives::zip32::PseudoExtendedKey; -use namada_core::address::{Address, MASP}; +use namada_core::address::Address; use namada_core::chain::{BlockHeight, ChainId, Epoch}; use namada_core::collections::HashMap; use namada_core::dec::Dec; @@ -16,30 +16,21 @@ use namada_core::ethereum_events::EthAddress; use namada_core::keccak::KeccakHash; use namada_core::key::{common, SchemeType}; use namada_core::masp::{MaspEpoch, PaymentAddress}; -use namada_core::string_encoding::StringEncoded; use namada_core::time::DateTimeUtc; -use namada_core::token::Amount; use namada_core::{storage, token}; use namada_governance::cli::onchain::{ DefaultProposal, PgfFundingProposal, PgfStewardProposal, }; use namada_ibc::IbcShieldingData; -use namada_io::{display_line, Io}; use namada_token::masp::utils::RetryStrategy; use namada_tx::data::GasLimit; use namada_tx::Memo; use serde::{Deserialize, Serialize}; use zeroize::Zeroizing; -use crate::error::Error; use crate::eth_bridge::bridge_pool; use crate::ibc::core::host::types::identifiers::{ChannelId, PortId}; -use crate::ibc::{NamadaMemo, NamadaMemoData}; -use crate::rpc::{ - get_registry_from_xcs_osmosis_contract, osmosis_denom_from_namada_denom, - query_osmosis_pool_routes, -}; -use crate::signing::{gen_disposable_signing_key, SigningTxData}; +use crate::signing::SigningTxData; use crate::wallet::{DatedSpendingKey, DatedViewingKey}; use crate::{rpc, tx, Namada}; @@ -486,321 +477,6 @@ impl TxUnshieldingTransfer { } } -/// Individual hop of some route to take through Osmosis pools. -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct OsmosisPoolHop { - /// The id of the pool to use on Osmosis. - pub pool_id: String, - /// The output denomination expected from the - /// pool on Osmosis. - pub token_out_denom: String, -} - -impl FromStr for OsmosisPoolHop { - type Err = String; - - fn from_str(s: &str) -> Result { - s.split_once(':').map_or_else( - || { - Err(format!( - "Expected : string, but found \ - {s:?} instead" - )) - }, - |(pool_id, token_out_denom)| { - Ok(OsmosisPoolHop { - pool_id: pool_id.to_owned(), - token_out_denom: token_out_denom.to_owned(), - }) - }, - ) - } -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -/// Constraints on the osmosis swap -pub enum Slippage { - /// Specifies the minimum amount to be received - MinOutputAmount(Amount), - /// A time-weighted average price - Twap { - /// The maximum percentage difference allowed between the estimated and - /// actual trade price. This must be a decimal number in the range - /// `[0, 100]`. - slippage_percentage: String, - /// The time period (in seconds) over which the average price is - /// calculated - window_seconds: u64, - }, -} - -/// An token swap on Osmosis -#[derive(Debug, Clone)] -pub struct TxOsmosisSwap { - /// The IBC transfer data - pub transfer: TxIbcTransfer, - /// The token we wish to receive (on Namada) - pub output_denom: String, - /// Address of the recipient on Namada - pub recipient: Either, - /// Address to receive funds exceeding the minimum amount, - /// in case of IBC shieldings - /// - /// If unspecified, a disposable address is generated to - /// receive funds with - pub overflow: Option, - /// Constraints on the osmosis swap - pub slippage: Slippage, - /// Recovery address (on Osmosis) in case of failure - pub local_recovery_addr: String, - /// The route to take through Osmosis pools - pub route: Option>, - /// A REST rpc endpoint to Osmosis - pub osmosis_rest_rpc: String, -} - -impl TxOsmosisSwap { - /// Create an IBC transfer from the input arguments - pub async fn into_ibc_transfer( - self, - ctx: &impl Namada, - ) -> crate::error::Result> { - #[derive(Serialize)] - struct Memo { - wasm: Wasm, - } - - #[derive(Serialize)] - struct Wasm { - contract: String, - msg: Message, - } - - #[derive(Serialize)] - struct Message { - osmosis_swap: OsmosisSwap, - } - - #[derive(Serialize)] - struct OsmosisSwap { - receiver: String, - output_denom: String, - slippage: Slippage, - on_failed_delivery: LocalRecoveryAddr, - route: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - final_memo: Option>, - } - - #[derive(Serialize)] - struct LocalRecoveryAddr { - local_recovery_addr: String, - } - - #[inline] - fn assert_json_obj( - value: serde_json::Value, - ) -> serde_json::Map { - match value { - serde_json::Value::Object(x) => x, - _ => unreachable!(), - } - } - - const OSMOSIS_SQS_SERVER: &str = "https://sqsprod.osmosis.zone"; - - let Self { - mut transfer, - recipient, - slippage, - local_recovery_addr, - route, - overflow, - osmosis_rest_rpc, - output_denom: namada_output_denom, - } = self; - - let recipient = recipient.map_either( - |addr| addr, - |payment_addr| async move { - let overflow_receiver = if let Some(overflow) = overflow { - overflow - } else { - let addr = (&gen_disposable_signing_key(ctx).await).into(); - display_line!( - ctx.io(), - "Sending unshielded funds to disposable address {addr}", - ); - addr - }; - (payment_addr, overflow_receiver) - }, - ); - - // validate `local_recovery_addr` and the contract addr - if !bech32::decode(&local_recovery_addr) - .is_ok_and(|(hrp, _, _)| hrp == "osmo") - { - // TODO: validate that addr has 20 bytes? - return Err(Error::Other(format!( - "Invalid Osmosis recovery address {local_recovery_addr:?}" - ))); - } - if !bech32::decode(&transfer.receiver) - .is_ok_and(|(hrp, _, _)| hrp == "osmo") - { - // TODO: validate that addr has 32 bytes? - return Err(Error::Other(format!( - "Invalid Osmosis contract address {local_recovery_addr:?}" - ))); - } - - let registry_xcs_addr = get_registry_from_xcs_osmosis_contract( - &osmosis_rest_rpc, - &transfer.receiver, - ) - .await?; - - let (osmosis_output_denom, namada_output_addr) = - osmosis_denom_from_namada_denom( - &osmosis_rest_rpc, - ®istry_xcs_addr, - &namada_output_denom, - ) - .await?; - - let route = if let Some(route) = route { - route - } else { - query_osmosis_pool_routes( - ctx, - &transfer.token, - transfer.amount, - transfer.channel_id.clone(), - &osmosis_output_denom, - OSMOSIS_SQS_SERVER, - ) - .await? - .pop() - .ok_or_else(|| { - Error::Other(format!( - "No route found to swap {:?} of {} with {}", - transfer.amount, transfer.token, namada_output_addr, - )) - })? - }; - - let (receiver, slippage, final_memo) = match recipient { - Either::Left(transparent_recipient) => { - (transparent_recipient.to_string(), slippage, None) - } - Either::Right(fut) => { - let (payment_addr, overflow_receiver) = fut.await; - - let amount_to_shield = match slippage { - Slippage::MinOutputAmount(amount_to_shield) => { - amount_to_shield - } - Slippage::Twap { .. } => todo!( - "Cannot compute min output amount from slippage TWAP \ - yet" - ), - }; - - let shielding_tx = tx::gen_ibc_shielding_transfer( - ctx, - GenIbcShieldingTransfer { - query: Query { - ledger_address: transfer.tx.ledger_address.clone(), - }, - output_folder: None, - target: - namada_core::masp::TransferTarget::PaymentAddress( - payment_addr, - ), - asset: IbcShieldingTransferAsset::Address( - namada_output_addr, - ), - amount: InputAmount::Validated( - token::DenominatedAmount::new( - amount_to_shield, - 0u8.into(), - ), - ), - expiration: transfer.tx.expiration.clone(), - }, - ) - .await? - .ok_or_else(|| { - Error::Other( - "Failed to generate IBC shielding transfer".to_owned(), - ) - })?; - - let memo = assert_json_obj( - serde_json::to_value(&NamadaMemo { - namada: NamadaMemoData::OsmosisSwap { - shielding_data: StringEncoded::new( - IbcShieldingData(shielding_tx), - ), - shielded_amount: amount_to_shield, - overflow_receiver, - }, - }) - .unwrap(), - ); - - ( - MASP.to_string(), - Slippage::MinOutputAmount(amount_to_shield), - Some(memo), - ) - } - }; - - let cosmwasm_memo = Memo { - wasm: Wasm { - contract: transfer.receiver.clone(), - msg: Message { - osmosis_swap: OsmosisSwap { - output_denom: osmosis_output_denom, - slippage, - final_memo, - receiver, - on_failed_delivery: LocalRecoveryAddr { - local_recovery_addr, - }, - route, - }, - }, - }, - }; - let namada_memo = transfer.ibc_memo.take().map(|memo| { - assert_json_obj( - serde_json::to_value(&NamadaMemo { - namada: NamadaMemoData::Memo(memo), - }) - .unwrap(), - ) - }); - - let memo = { - let mut m = serde_json::to_value(&cosmwasm_memo).unwrap(); - let m_obj = m.as_object_mut().unwrap(); - - if let Some(mut namada_memo) = namada_memo { - m_obj.append(&mut namada_memo); - } - - m - }; - - transfer.ibc_memo = Some(serde_json::to_string(&memo).unwrap()); - Ok(transfer) - } -} - /// IBC transfer transaction arguments #[derive(Clone, Debug)] pub struct TxIbcTransfer { @@ -3242,26 +2918,14 @@ pub struct GenIbcShieldingTransfer { pub output_folder: Option, /// The target address pub target: C::TransferTarget, + /// The token address which could be a non-namada address + pub token: String, /// Transferred token amount pub amount: InputAmount, /// The optional expiration of the masp shielding transaction pub expiration: TxExpiration, - /// Asset to shield over IBC to Namada - pub asset: IbcShieldingTransferAsset, -} - -/// IBC shielding transfer asset, to be used by [`GenIbcShieldingTransfer`] -#[derive(Clone, Debug)] -pub enum IbcShieldingTransferAsset { - /// Attempt to look-up the address of the asset to shield on Namada - LookupNamadaAddress { - /// The token address which could be a non-namada address - token: String, - /// Port ID via which the token is received - port_id: PortId, - /// Channel ID via which the token is received - channel_id: ChannelId, - }, - /// Namada address of the token that will be received. - Address(C::Address), + /// Port ID via which the token is received + pub port_id: PortId, + /// Channel ID via which the token is received + pub channel_id: ChannelId, } diff --git a/crates/sdk/src/rpc.rs b/crates/sdk/src/rpc.rs index eac8e2159e..2e9792b61c 100644 --- a/crates/sdk/src/rpc.rs +++ b/crates/sdk/src/rpc.rs @@ -2,7 +2,6 @@ #![allow(clippy::result_large_err)] -use core::str::FromStr; use std::cell::Cell; use std::collections::{BTreeMap, BTreeSet}; use std::ops::ControlFlow; @@ -17,9 +16,6 @@ use namada_core::arith::checked; use namada_core::chain::{BlockHeight, Epoch}; use namada_core::collections::{HashMap, HashSet}; use namada_core::hash::Hash; -use namada_core::ibc::apps::nft_transfer::types::TracePrefix; -use namada_core::ibc::apps::transfer::types::PrefixedDenom; -use namada_core::ibc::core::host::types::identifiers::ChannelId; use namada_core::ibc::IbcTokenHash; use namada_core::key::common; use namada_core::masp::MaspEpoch; @@ -40,11 +36,9 @@ use namada_governance::storage::proposal::{ use namada_governance::utils::{ compute_proposal_result, ProposalResult, ProposalVotes, Vote, }; -use namada_ibc::core::host::types::identifiers::PortId; use namada_ibc::storage::{ ibc_trace_key, ibc_trace_key_prefix, is_ibc_trace_key, }; -use namada_ibc::trace::calc_ibc_token_hash; use namada_io::{display_line, edisplay_line, Client, Io}; use namada_parameters::{storage as params_storage, EpochDuration}; use namada_proof_of_stake::parameters::PosParams; @@ -57,9 +51,9 @@ use namada_state::{BlockHeader, LastBlock}; use namada_token::masp::MaspTokenRewardData; use namada_tx::data::{BatchedTxResult, DryRunResult, ResultCode, TxResult}; use namada_tx::event::{Batch as BatchAttr, Code as CodeAttr}; -use serde::{Deserialize, Serialize}; +use serde::Serialize; -use crate::args::{InputAmount, OsmosisPoolHop}; +use crate::args::InputAmount; use crate::control_flow::time; use crate::error::{EncodingError, Error, QueryError, TxSubmitError}; use crate::events::{extend, Event}; @@ -71,7 +65,6 @@ use crate::queries::RPC; use crate::tendermint::block::Height; use crate::tendermint::merkle::proof::ProofOps; use crate::tendermint_rpc::query::Query; -use crate::tx::get_ibc_src_port_channel; use crate::{error, Namada, Tx}; /// Query an estimate of the maximum block time. @@ -1525,376 +1518,3 @@ pub async fn query_ibc_denom( token.as_ref().to_string() } - -/// Query the registry contract embedded in the state of -/// an input Crosschain Swaps Osmosis contract. -pub async fn get_registry_from_xcs_osmosis_contract( - rest_rpc_addr: &str, - xcs_contract_addr: &str, -) -> Result { - #[derive(Deserialize)] - struct RespData { - models: Vec, - } - - #[derive(Deserialize)] - struct Model { - key: String, - value: String, - } - - #[derive(Deserialize)] - struct XcsConfig { - registry_contract: String, - } - - let request_url = format!( - "{rest_rpc_addr}/cosmwasm/wasm/v1/contract/{xcs_contract_addr}/state" - ); - let RespData { models } = reqwest::get(&request_url) - .await - .map_err(|e| { - Error::Other(format!( - "Failed to fetch headers of request {request_url:?}: {e}" - )) - })? - .json() - .await - .map_err(|e| { - Error::Other(format!( - "Failed to fetch JSON body of request {request_url:?}: {e}" - )) - })?; - - let Some(Model { - value: base64_encoded_config, - .. - }) = models.into_iter().find(|Model { key, .. }| { - // NB: this value corresponds to the hex encoding of the - // string "config". the crosschain swaps contract of the set - // of xcs contracts stores, in its internal state, the params - // it was initialized with, namely the address of the registry - // contract. the point behind querying the initialization - // params is to ultimately query the address of the registry - // contract. - const HEX_ENCODED_CONFIG_KEY: &str = "636F6E666967"; - key == HEX_ENCODED_CONFIG_KEY - }) - else { - return Err(Error::Other(format!( - "Could not find config of XCS contract {xcs_contract_addr}" - ))); - }; - - let xcs_cfg_json = data_encoding::BASE64 - .decode(base64_encoded_config.as_bytes()) - .map_err(|e| Error::Other(e.to_string()))?; - - let XcsConfig { registry_contract } = serde_json::from_slice(&xcs_cfg_json) - .map_err(|e| Error::Other(e.to_string()))?; - - Ok(registry_contract) -} - -/// Given a Namada asset returned from an Osmosis swap, -/// find the corresponding asset denom on Osmosis. -/// -/// This is done by querying the XCS registry contract. The Namada asset -/// is also returned, parsed as an [`Address`]. -pub async fn osmosis_denom_from_namada_denom( - rest_rpc_addr: &str, - registry_contract_addr: &str, - namada_denom: &str, -) -> Result<(String, Address), Error> { - async fn fetch_contract_data( - contract_addr: &str, - rest_rpc_addr: &str, - json_query: &str, - ) -> Result { - #[derive(Deserialize)] - struct RespData { - data: String, - } - - let encoded_query = data_encoding::BASE64.encode(json_query.as_bytes()); - let request_url = format!( - "{rest_rpc_addr}/cosmwasm/wasm/v1/contract/{contract_addr}/smart/\ - {encoded_query}" - ); - - let RespData { data } = reqwest::get(&request_url) - .await - .map_err(|e| { - Error::Other(format!( - "Failed to fetch headers of request {request_url:?}: {e}" - )) - })? - .json() - .await - .map_err(|e| { - Error::Other(format!( - "Failed to fetch JSON body of request {request_url:?}: {e}" - )) - })?; - - Ok(data) - } - - let chain_name_req = |prefix| { - format!( - r#"{{"get_chain_name_from_bech32_prefix": {{"prefix": "{prefix}" }} }}"# - ) - }; - let channel_pair_req = |src, dest| { - format!( - r#"{{"get_channel_from_chain_pair": {{"source_chain": "{src}", "destination_chain": "{dest}" }} }}"# - ) - }; - let dest_chain_req = |on_chain, via_channel| { - format!( - r#"{{"get_destination_chain_from_source_chain_via_channel": {{"on_chain": "{on_chain}", "via_channel": "{via_channel}" }} }}"# - ) - }; - - //////////////////////////////////////////////////////////////////////////// - - let nam_denom = PrefixedDenom::from_str(namada_denom).map_err(|e| { - Error::Other(format!( - "Could not parse {namada_denom} as a trace path {e}" - )) - })?; - - let namada_chain_name = fetch_contract_data( - registry_contract_addr, - rest_rpc_addr, - &chain_name_req("tnam"), - ) - .await?; - let osmosis_chain_name = fetch_contract_data( - registry_contract_addr, - rest_rpc_addr, - &chain_name_req("osmo"), - ) - .await?; - - if nam_denom.trace_path.is_empty() { - // Namada native asset - - let address = nam_denom - .base_denom - .as_str() - .parse::
() - .map_err(|err| { - Error::Encode(EncodingError::Decoding(format!( - "Failed to parse base denom {} as Namada address: {err}", - nam_denom.base_denom - ))) - })?; - - // validate that the base denom is not another ibc token - if matches!(&address, Address::Internal(InternalAddress::IbcToken(_))) { - return Err(Error::Encode(EncodingError::Decoding(format!( - "Base denom {} cannot be an IBC token hash", - nam_denom.base_denom - )))); - } - - let channel_from_osmosis_to_namada = fetch_contract_data( - registry_contract_addr, - rest_rpc_addr, - &channel_pair_req(&osmosis_chain_name, &namada_chain_name), - ) - .await?; - - Ok(( - format!( - "transfer/{channel_from_osmosis_to_namada}/{}", - nam_denom.base_denom - ), - address, - )) - } else { - let channel_from_namada_to_src: ChannelId = nam_denom - .trace_path - .to_string() - .strip_prefix("transfer/") - .ok_or_else(|| { - Error::Other( - "Expected the output denom to originate from the transfer \ - port" - .to_string(), - ) - })? - .parse() - .map_err(|_| { - Error::Other(format!( - "Expected a single hop of the form `transfer/channel` in \ - {namada_denom}" - )) - })?; - - // we get chain name from which the base denom originated - let src_chain_name = fetch_contract_data( - registry_contract_addr, - rest_rpc_addr, - &dest_chain_req( - &namada_chain_name, - channel_from_namada_to_src.as_str(), - ), - ) - .await?; - - if src_chain_name == osmosis_chain_name { - // this is an osmosis native token - Ok(( - nam_denom.base_denom.to_string(), - namada_ibc::trace::ibc_token(namada_denom), - )) - } else { - // this asset is not native to osmosis - let channel_from_osmosis_to_src = fetch_contract_data( - registry_contract_addr, - rest_rpc_addr, - &channel_pair_req(&osmosis_chain_name, &src_chain_name), - ) - .await?; - - Ok(( - format!( - "transfer/{channel_from_osmosis_to_src}/{}", - nam_denom.base_denom - ), - namada_ibc::trace::ibc_token(namada_denom), - )) - } - } -} - -/// Query a route of Osmosis liquidity pools -/// for swapping betwixt token and output_denom -/// assets. -pub async fn query_osmosis_pool_routes( - ctx: &impl Namada, - token: &Address, - amount: InputAmount, - channel_id: ChannelId, - output_denom: &str, - osmosis_sqs_server_url: &str, -) -> Result>, Error> { - #[derive(Deserialize)] - struct PoolHop { - id: u64, - token_out_denom: String, - } - - impl From for OsmosisPoolHop { - fn from(value: PoolHop) -> Self { - Self { - pool_id: value.id.to_string(), - token_out_denom: value.token_out_denom, - } - } - } - - #[derive(Deserialize)] - struct Route { - pools: Vec, - } - - #[derive(Deserialize)] - struct ResponseOk { - route: Vec, - } - - #[derive(Deserialize)] - struct ResponseErr { - message: String, - } - - let coin = { - let denom = query_ibc_denom(ctx, token.to_string(), None).await; - let amount = validate_amount(ctx, amount, token, false).await?; - - let PrefixedDenom { - mut trace_path, - base_denom, - } = PrefixedDenom::from_str(&denom).map_err(|_| { - Error::Other(format!( - "Could not decode {token} as an IBC token address" - )) - })?; - - let prefix_on_namada = - TracePrefix::new(PortId::transfer(), channel_id.clone()); - - if trace_path.starts_with(&prefix_on_namada) { - // we received an asset from osmosis, so the asset we - // send back won't have our `transfer/channel` prefix - trace_path.remove_prefix(&prefix_on_namada); - } else { - // in this case, osmosis will prefix the asset it receives - // with the channel to namada - let channel = - get_ibc_src_port_channel(ctx, &PortId::transfer(), &channel_id) - .await? - .1; - trace_path - .add_prefix(TracePrefix::new(PortId::transfer(), channel)); - } - - let amount = amount.redenominate(0); - - let token_denom = if trace_path.is_empty() { - base_denom.to_string() - } else { - format!( - "ibc/{}", - calc_ibc_token_hash( - PrefixedDenom { - trace_path, - base_denom - } - .to_string() - ) - ) - }; - - format!("{amount}{token_denom}") - }; - - let client = reqwest::Client::new(); - let response = client - .get(format!("{osmosis_sqs_server_url}/router/quote")) - .query(&[ - ("tokenIn", coin.as_str()), - ("tokenOutDenom", output_denom), - ("humanDenoms", "false"), - ]) - .send() - .await - .map_err(|err| { - Error::Other(format!("Failed to query Osmosis SQS: {err}",)) - })?; - - if !response.status().is_success() { - let ResponseErr { message } = response.json().await.map_err(|err| { - Error::Other(format!( - "Failed to read failure response from HTTP request body: {err}" - )) - })?; - return Err(Error::Other(format!( - "Invalid Osmosis SQS query: {message}" - ))); - } - - let ResponseOk { route } = response.json().await.map_err(|err| { - Error::Other(format!( - "Failed to read success response from HTTP request body: {err}" - )) - })?; - - Ok(route - .into_iter() - .map(|r| r.pools.into_iter().map(OsmosisPoolHop::from).collect()) - .collect()) -} diff --git a/crates/sdk/src/signing.rs b/crates/sdk/src/signing.rs index 1252373faa..a2e92b5cb7 100644 --- a/crates/sdk/src/signing.rs +++ b/crates/sdk/src/signing.rs @@ -410,7 +410,11 @@ pub async fn aux_signing_data( }; let fee_payer = if disposable_signing_key { - gen_disposable_signing_key(context).await + context + .wallet_mut() + .await + .gen_disposable_signing_key(&mut OsRng) + .to_public() } else { match &args.wrapper_fee_payer { Some(keypair) => keypair.clone(), @@ -493,17 +497,6 @@ pub async fn generate_tx_signatures( }) } -/// Generate a disposable signing key. -pub async fn gen_disposable_signing_key( - context: &impl Namada, -) -> common::PublicKey { - context - .wallet_mut() - .await - .gen_disposable_signing_key(&mut OsRng) - .to_public() -} - /// Information about the post-fee balance of the tx's source. Used to correctly /// handle balance validation in the inner tx #[derive(Debug)] diff --git a/crates/sdk/src/tx.rs b/crates/sdk/src/tx.rs index 9c8c3834e5..19a6a5ba17 100644 --- a/crates/sdk/src/tx.rs +++ b/crates/sdk/src/tx.rs @@ -3884,33 +3884,22 @@ pub async fn gen_ibc_shielding_transfer( args: args::GenIbcShieldingTransfer, ) -> Result> { let source = IBC; - - let token = match args.asset { - args::IbcShieldingTransferAsset::Address(addr) => addr, - args::IbcShieldingTransferAsset::LookupNamadaAddress { - token, - port_id, - channel_id, - } => { - let (src_port_id, src_channel_id) = - get_ibc_src_port_channel(context, &port_id, &channel_id) - .await?; - let ibc_denom = - rpc::query_ibc_denom(context, &token, Some(&source)).await; - - namada_ibc::received_ibc_token( - &ibc_denom, - &src_port_id, - &src_channel_id, - &port_id, - &channel_id, - ) - .map_err(|e| { - Error::Other(format!("Getting IBC Token failed: error {e}")) - })? - } - }; - + let (src_port_id, src_channel_id) = + get_ibc_src_port_channel(context, &args.port_id, &args.channel_id) + .await?; + let ibc_denom = + rpc::query_ibc_denom(context, &args.token, Some(&source)).await; + // Need to check the prefix + let token = namada_ibc::received_ibc_token( + &ibc_denom, + &src_port_id, + &src_channel_id, + &args.port_id, + &args.channel_id, + ) + .map_err(|e| { + Error::Other(format!("Getting IBC Token failed: error {e}")) + })?; let validated_amount = validate_amount(context, args.amount, &token, false).await?; @@ -3947,7 +3936,7 @@ pub async fn gen_ibc_shielding_transfer( Ok(shielded_transfer.map(|st| st.masp_tx)) } -pub(crate) async fn get_ibc_src_port_channel( +async fn get_ibc_src_port_channel( context: &impl Namada, dest_port_id: &PortId, dest_channel_id: &ChannelId, diff --git a/crates/tests/fixtures/osmosis_data/wasm_bytecode/crosschain_registry.wasm b/crates/tests/fixtures/osmosis_data/wasm_bytecode/crosschain_registry.wasm deleted file mode 100644 index ebd2324e65..0000000000 Binary files a/crates/tests/fixtures/osmosis_data/wasm_bytecode/crosschain_registry.wasm and /dev/null differ diff --git a/crates/tests/fixtures/osmosis_data/wasm_bytecode/crosschain_swaps.wasm b/crates/tests/fixtures/osmosis_data/wasm_bytecode/crosschain_swaps.wasm deleted file mode 100644 index c79e7121df..0000000000 Binary files a/crates/tests/fixtures/osmosis_data/wasm_bytecode/crosschain_swaps.wasm and /dev/null differ diff --git a/crates/tests/fixtures/osmosis_data/wasm_bytecode/swaprouter.wasm b/crates/tests/fixtures/osmosis_data/wasm_bytecode/swaprouter.wasm deleted file mode 100644 index e43efcb25c..0000000000 Binary files a/crates/tests/fixtures/osmosis_data/wasm_bytecode/swaprouter.wasm and /dev/null differ diff --git a/crates/tests/src/e2e/helpers.rs b/crates/tests/src/e2e/helpers.rs index 1b911ce53b..3df93fddc7 100644 --- a/crates/tests/src/e2e/helpers.rs +++ b/crates/tests/src/e2e/helpers.rs @@ -497,7 +497,6 @@ pub fn make_hermes_config( hermes_dir: &TestDir, test_a: &Test, test_b: &Test, - relayer: Option<&str>, ) -> Result<()> { let mut config = toml::map::Map::new(); @@ -536,17 +535,12 @@ pub fn make_hermes_config( config.insert("telemetry".to_owned(), Value::Table(telemetry)); let chains = vec![ - match CosmosChainType::chain_type(test_a.net.chain_id.as_str()) { - Ok(chain_type) => make_hermes_chain_config_for_cosmos( - hermes_dir, chain_type, test_a, relayer, - ), - Err(_) => make_hermes_chain_config(hermes_dir, test_a), - }, + make_hermes_chain_config(test_a), match CosmosChainType::chain_type(test_b.net.chain_id.as_str()) { Ok(chain_type) => make_hermes_chain_config_for_cosmos( - hermes_dir, chain_type, test_b, relayer, + hermes_dir, chain_type, test_b, ), - Err(_) => make_hermes_chain_config(hermes_dir, test_b), + Err(_) => make_hermes_chain_config(test_b), }, ]; @@ -564,7 +558,7 @@ pub fn make_hermes_config( Ok(()) } -fn make_hermes_chain_config(hermes_dir: &TestDir, test: &Test) -> Value { +fn make_hermes_chain_config(test: &Test) -> Value { let chain_id = test.net.chain_id.as_str(); let rpc_addr = get_actor_rpc(test, Who::Validator(0)); let rpc_addr = rpc_addr.strip_prefix("http://").unwrap(); @@ -604,13 +598,6 @@ fn make_hermes_chain_config(hermes_dir: &TestDir, test: &Test) -> Value { chain.insert("max_block_time".to_owned(), Value::String("60s".to_owned())); - let hermes_dir: &Path = hermes_dir.as_ref(); - let key_dir = hermes_dir.join("hermes/keys"); - chain.insert( - "key_store_folder".to_owned(), - Value::String(key_dir.to_string_lossy().to_string()), - ); - Value::Table(chain) } @@ -618,14 +605,11 @@ fn make_hermes_chain_config_for_cosmos( hermes_dir: &TestDir, chain_type: CosmosChainType, test: &Test, - relayer: Option<&str>, ) -> Value { let mut table = toml::map::Map::new(); table.insert("mode".to_owned(), Value::String("push".to_owned())); - let url = format!( - "ws://127.0.0.1:{}/websocket", - chain_type.get_rpc_port_number() - ); + let offset = chain_type.get_offset(); + let url = format!("ws://127.0.0.1:6416{}/websocket", offset); table.insert("url".to_owned(), Value::String(url)); table.insert("batch_delay".to_owned(), Value::String("500ms".to_owned())); let event_source = Value::Table(table); @@ -639,17 +623,11 @@ fn make_hermes_chain_config_for_cosmos( chain.insert( "rpc_addr".to_owned(), - Value::String(format!( - "http://127.0.0.1:{}", - chain_type.get_rpc_port_number() - )), + Value::String(format!("http://127.0.0.1:6416{}", offset)), ); chain.insert( "grpc_addr".to_owned(), - Value::String(format!( - "http://127.0.0.1:{}", - chain_type.get_grpc_port_number() - )), + Value::String(format!("http://127.0.0.1:{}", offset + 9090)), ); chain.insert("event_source".to_owned(), event_source); @@ -659,7 +637,7 @@ fn make_hermes_chain_config_for_cosmos( ); chain.insert( "key_name".to_owned(), - Value::String(relayer.unwrap_or(constants::COSMOS_RELAYER).to_string()), + Value::String(setup::constants::COSMOS_RELAYER.to_string()), ); let hermes_dir: &Path = hermes_dir.as_ref(); let key_dir = hermes_dir.join("hermes/keys"); @@ -668,14 +646,10 @@ fn make_hermes_chain_config_for_cosmos( Value::String(key_dir.to_string_lossy().to_string()), ); chain.insert("store_prefix".to_owned(), Value::String("ibc".to_owned())); - chain.insert("max_gas".to_owned(), Value::Integer(500_000_000)); - chain.insert("gas_multiplier".to_owned(), Value::Float(2.3)); + chain.insert("max_gas".to_owned(), Value::Integer(500_000)); + chain.insert("gas_multiplier".to_owned(), Value::Float(1.3)); let mut table = toml::map::Map::new(); - if let CosmosChainType::Osmosis = chain_type { - table.insert("price".to_owned(), Value::Float(0.01)); - } else { - table.insert("price".to_owned(), Value::Float(0.001)); - } + table.insert("price".to_owned(), Value::Float(0.001)); table.insert("denom".to_owned(), Value::String("stake".to_string())); chain.insert("gas_price".to_owned(), Value::Table(table)); @@ -698,8 +672,9 @@ pub fn update_cosmos_config(test: &Test) -> Result<()> { *timeout_propose = "1s".into(); } } - let chain_type = - CosmosChainType::chain_type(test.net.chain_id.as_str()).unwrap(); + let offset = CosmosChainType::chain_type(test.net.chain_id.as_str()) + .unwrap() + .get_offset(); let p2p = values .get_mut("p2p") .expect("Test failed") @@ -708,8 +683,7 @@ pub fn update_cosmos_config(test: &Test) -> Result<()> { let Some(laddr) = p2p.get_mut("laddr") else { panic!("Test failed") }; - *laddr = - format!("tcp://0.0.0.0:{}", chain_type.get_p2p_port_number()).into(); + *laddr = format!("tcp://0.0.0.0:266{}{}", offset, offset).into(); let rpc = values .get_mut("rpc") .expect("Test failed") @@ -718,8 +692,7 @@ pub fn update_cosmos_config(test: &Test) -> Result<()> { let Some(laddr) = rpc.get_mut("laddr") else { panic!("Test failed") }; - *laddr = - format!("tcp://0.0.0.0:{}", chain_type.get_rpc_port_number()).into(); + *laddr = format!("tcp://0.0.0.0:6416{offset}").into(); let mut file = OpenOptions::new() .write(true) @@ -784,37 +757,14 @@ pub fn update_cosmos_config(test: &Test) -> Result<()> { serde_json::to_writer_pretty(writer, &genesis) .expect("Writing Cosmos genesis.toml failed"); - if matches!(chain_type, CosmosChainType::Osmosis) { - let client_path = cosmos_dir.join("config/client.toml"); - let s = std::fs::read_to_string(&client_path) - .expect("Reading Osmosis client config failed"); - let mut values = s - .parse::() - .expect("Parsing Osmosis client config failed"); - let Some(laddr) = values.get_mut("node") else { - panic!("Test failed") - }; - *laddr = format!("tcp://0.0.0.0:{}", chain_type.get_rpc_port_number()) - .into(); - let mut file = OpenOptions::new() - .write(true) - .truncate(true) - .open(&client_path)?; - file.write_all(values.to_string().as_bytes()).map_err(|e| { - eyre!(format!( - "Writing a Osmosis client config file failed: {}", - e - )) - })?; - } - Ok(()) } pub fn get_cosmos_rpc_address(test: &Test) -> String { - let chain_type = - CosmosChainType::chain_type(test.net.chain_id.as_str()).unwrap(); - format!("127.0.0.1:{}", chain_type.get_rpc_port_number()) + let offset = CosmosChainType::chain_type(test.net.chain_id.as_str()) + .unwrap() + .get_offset(); + format!("127.0.0.1:6416{offset}") } pub fn find_cosmos_address( diff --git a/crates/tests/src/e2e/ibc_tests.rs b/crates/tests/src/e2e/ibc_tests.rs index e2698db993..2e63db39f5 100644 --- a/crates/tests/src/e2e/ibc_tests.rs +++ b/crates/tests/src/e2e/ibc_tests.rs @@ -11,7 +11,6 @@ use core::str::FromStr; use core::time::Duration; -use std::fs::File; use std::path::{Path, PathBuf}; use color_eyre::eyre::Result; @@ -42,11 +41,9 @@ use namada_sdk::ibc::core::host::types::identifiers::{ use namada_sdk::ibc::primitives::proto::Any; use namada_sdk::ibc::storage::*; use namada_sdk::ibc::trace::ibc_token; -use namada_sdk::ibc::IbcShieldingData; use namada_sdk::token::Amount; use namada_test_utils::TestWasms; use prost::Message; -use serde_json::json; use setup::constants::*; use sha2::{Digest, Sha256}; @@ -59,10 +56,10 @@ use crate::e2e::ledger_tests::{ start_namada_ledger_node_wait_wasm, write_json_file, }; use crate::e2e::setup::{ - self, apply_use_device, osmosis_fixtures_dir, run_cosmos_cmd, - run_cosmos_cmd_homeless, run_hermes_cmd, set_ethereum_bridge_mode, - setup_cosmos, setup_hermes, sleep, working_dir, Bin, CosmosChainType, - NamadaCmd, Test, TestDir, Who, ENV_VAR_COSMWASM_CONTRACT_DIR, + self, apply_use_device, run_cosmos_cmd, run_hermes_cmd, + set_ethereum_bridge_mode, setup_cosmos, setup_hermes, sleep, working_dir, + Bin, CosmosChainType, NamadaCmd, Test, TestDir, Who, + ENV_VAR_COSMWASM_CONTRACT_DIR, }; use crate::ibc::primitives::Signer; use crate::strings::TX_APPLIED_SUCCESS; @@ -143,7 +140,6 @@ fn ibc_transfers() -> Result<()> { None, None, None, - None, false, )?; wait_for_packet_relay( @@ -221,7 +217,6 @@ fn ibc_transfers() -> Result<()> { None, None, None, - None, false, )?; wait_for_packet_relay( @@ -304,7 +299,6 @@ fn ibc_transfers() -> Result<()> { None, None, None, - None, true, )?; wait_for_packet_relay( @@ -359,7 +353,6 @@ fn ibc_transfers() -> Result<()> { None, None, None, - None, false, )?; wait_for_packet_relay( @@ -388,7 +381,6 @@ fn ibc_transfers() -> Result<()> { Some(Duration::new(10, 0)), None, None, - None, false, )?; // wait for the timeout @@ -421,7 +413,6 @@ fn ibc_transfers() -> Result<()> { None, None, None, - None, true, )?; wait_for_packet_relay( @@ -452,7 +443,6 @@ fn ibc_transfers() -> Result<()> { Some(Duration::new(10, 0)), None, None, - None, true, )?; // wait for the timeout @@ -615,7 +605,6 @@ fn ibc_nft_transfers() -> Result<()> { None, None, None, - None, false, )?; clear_packet(&hermes_dir, &port_id_namada, &channel_id_namada, &test)?; @@ -679,7 +668,6 @@ fn ibc_nft_transfers() -> Result<()> { None, None, None, - None, true, )?; clear_packet(&hermes_dir, &port_id_namada, &channel_id_namada, &test)?; @@ -1122,7 +1110,6 @@ fn ibc_rate_limit() -> Result<()> { None, None, None, - None, false, )?; @@ -1142,7 +1129,6 @@ fn ibc_rate_limit() -> Result<()> { Some( "Transfer exceeding the per-epoch throughput limit is not allowed", ), - None, false, )?; @@ -1166,7 +1152,6 @@ fn ibc_rate_limit() -> Result<()> { None, None, None, - None, false, )?; @@ -1205,80 +1190,6 @@ fn ibc_rate_limit() -> Result<()> { Ok(()) } -/// Create a packet forward memo and serialize it -fn packet_forward_memo( - receiver: Signer, - port_id: &PortId, - channel_id: &ChannelId, - timeout: Option, - next: Option>, -) -> String { - serde_json::to_string(&serde_json::Value::Object( - packet_forward_memo_value(receiver, port_id, channel_id, timeout, next), - )) - .expect("Test failed") -} - -fn packet_forward_memo_value( - receiver: Signer, - port_id: &PortId, - channel_id: &ChannelId, - timeout: Option, - next: Option>, -) -> serde_json::Map { - let value = - serde_json::to_value(&ibc_middleware_packet_forward::PacketMetadata { - forward: ForwardMetadata { - receiver, - port: port_id.clone(), - channel: channel_id.clone(), - timeout: timeout.map(|t| { - ibc_middleware_packet_forward::Duration::from_dur( - dur::Duration::from_std(t), - ) - }), - retries: Some(0), - next, - }, - }) - .expect("Test failed"); - - if let serde_json::Value::Object(memo) = value { - memo - } else { - unreachable!() - } -} - -fn shielded_recv_memo_value( - masp_transfer_path: &Path, - shielded_amount: Amount, - overflow_receiver: namada_core::address::Address, -) -> serde_json::Map { - use namada_core::string_encoding::StringEncoded; - use namada_sdk::ibc::{NamadaMemo, NamadaMemoData}; - - let transfer = - std::fs::read_to_string(masp_transfer_path).expect("Test failed"); - let tx = StringEncoded::new( - IbcShieldingData::from_str(&transfer).expect("Test failed"), - ); - let data = NamadaMemoData::OsmosisSwap { - shielding_data: tx, - shielded_amount, - overflow_receiver, - }; - - let value = serde_json::to_value(&NamadaMemo { namada: data }) - .expect("Test failed"); - - if let serde_json::Value::Object(memo) = value { - memo - } else { - unreachable!() - } -} - /// Test the happy flows of ibc pfm /// /// Setup: Two instances of Gaia and one @@ -1355,7 +1266,6 @@ fn ibc_pfm_happy_flows() -> Result<()> { &port_id_namada, &channel_id_namada_2, None, - None, ); transfer_from_cosmos( &test_gaia_1, @@ -1403,7 +1313,6 @@ fn ibc_pfm_happy_flows() -> Result<()> { &port_id_namada, &channel_id_namada_1, None, - None, ); transfer_from_cosmos( &test_gaia_2, @@ -1452,7 +1361,6 @@ fn ibc_pfm_happy_flows() -> Result<()> { None, None, None, - None, false, )?; @@ -1478,7 +1386,6 @@ fn ibc_pfm_happy_flows() -> Result<()> { &port_id_namada, &channel_id_namada_2, None, - None, ); transfer_from_cosmos( @@ -1529,7 +1436,6 @@ fn ibc_pfm_happy_flows() -> Result<()> { &port_id_namada, &channel_id_namada_1, None, - None, ); transfer_from_cosmos( &test_gaia_2, @@ -1566,7 +1472,6 @@ fn ibc_pfm_happy_flows() -> Result<()> { Ok(()) } - /// Test the flows of ibc pfm where the packet cannot be /// completed and refunds must be issued. /// @@ -1655,7 +1560,6 @@ fn ibc_pfm_unhappy_flows() -> Result<()> { &port_id_namada, &channel_id_namada_2, None, - None, ); transfer_from_cosmos( &test_gaia_1, @@ -1691,7 +1595,6 @@ fn ibc_pfm_unhappy_flows() -> Result<()> { &port_id_namada, &channel_id_namada_2, Some(Duration::new(1, 0)), - None, ); // Stop Hermes for timeout test let mut hermes_2 = bg_hermes_2.foreground(); @@ -1749,7 +1652,6 @@ fn ibc_pfm_unhappy_flows() -> Result<()> { None, None, None, - None, false, )?; @@ -1775,7 +1677,6 @@ fn ibc_pfm_unhappy_flows() -> Result<()> { &port_id_namada, &channel_id_namada_2, None, - None, ); transfer_from_cosmos( &test_gaia_1, @@ -1816,7 +1717,6 @@ fn ibc_pfm_unhappy_flows() -> Result<()> { &port_id_namada, &channel_id_namada_2, Some(Duration::new(1, 0)), - None, ); // Stop Hermes for timeout test let mut hermes_2 = bg_hermes_2.foreground(); @@ -1870,7 +1770,6 @@ fn ibc_pfm_unhappy_flows() -> Result<()> { &port_id_namada, &channel_id_namada_1, None, - None, ); transfer_from_cosmos( &test_gaia_2, @@ -1909,7 +1808,6 @@ fn ibc_pfm_unhappy_flows() -> Result<()> { &port_id_namada, &channel_id_namada_2, None, - None, ); transfer_from_cosmos( &test_gaia_1, @@ -1955,7 +1853,6 @@ fn ibc_pfm_unhappy_flows() -> Result<()> { &port_id_namada, &channel_id_namada_2, Some(Duration::new(1, 0)), - None, ); // Stop Hermes for timeout test let mut hermes_2 = bg_hermes_2.foreground(); @@ -2009,193 +1906,6 @@ fn ibc_pfm_unhappy_flows() -> Result<()> { Ok(()) } -/// Test that we are able to use the shielded-receive -/// middleware to shield funds specified in the memo -/// message. -#[test] -fn ibc_shielded_recv_middleware_happy_flow() -> Result<()> { - let update_genesis = - |mut genesis: templates::All, base_dir: &_| { - genesis.parameters.parameters.epochs_per_year = - epochs_per_year_from_min_duration(1800); - genesis.parameters.ibc_params.default_mint_limit = - Amount::max_signed(); - genesis - .parameters - .ibc_params - .default_per_epoch_throughput_limit = Amount::max_signed(); - setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) - }; - let (ledger, gaia, test, test_gaia) = - run_namada_cosmos(CosmosChainType::Gaia(None), update_genesis)?; - let _bg_ledger = ledger.background(); - let _bg_gaia = gaia.background(); - sleep(5); - - let hermes_dir = setup_hermes(&test, &test_gaia)?; - let port_id_namada = FT_PORT_ID.parse().unwrap(); - let port_id_gaia = FT_PORT_ID.parse().unwrap(); - let (channel_id_namada, channel_id_gaia) = create_channel_with_hermes( - &hermes_dir, - &test, - &test_gaia, - &port_id_namada, - &port_id_gaia, - )?; - - // Start relaying - let hermes = run_hermes(&hermes_dir)?; - let _bg_hermes = hermes.background(); - - // 1. Shield 10 NAM to AA_PAYMENT_ADDRESS - transfer_on_chain( - &test, - "shield", - ALBERT, - AA_PAYMENT_ADDRESS, - NAM, - 10, - ALBERT_KEY, - &[], - )?; - check_shielded_balance(&test, AA_VIEWING_KEY, NAM, 10)?; - - // 2. Unshield from A_SPENDING_KEY to B_SPENDING_KEY, - // using the packet forward and shielded receive - // middlewares - let nam_addr = find_address(&test, NAM)?; - let overflow_addr = "tnam1qrqzqa0l0rzzrlr20n487l6n865t8ndv6uhseulq"; - let ibc_denom_on_gaia = format!("transfer/{channel_id_gaia}/{nam_addr}"); - let memo_path = gen_ibc_shielding_data( - &test, - AB_PAYMENT_ADDRESS, - &ibc_denom_on_gaia, - 8, - &port_id_namada, - &channel_id_namada, - )?; - let memo = packet_forward_memo( - MASP.to_string().into(), - &PortId::transfer(), - &channel_id_namada, - None, - Some(shielded_recv_memo_value( - &memo_path, - Amount::native_whole(8), - overflow_addr.parse().unwrap(), - )), - ); - transfer( - &test, - A_SPENDING_KEY, - "PacketForwardMiddleware", - NAM, - 10, - Some(ALBERT_KEY), - &PortId::transfer(), - &channel_id_namada, - None, - None, - None, - Some(&memo), - true, - )?; - wait_for_packet_relay(&hermes_dir, &port_id_gaia, &channel_id_gaia, &test)?; - - // Check the token on Namada - check_shielded_balance(&test, AA_VIEWING_KEY, NAM, 0)?; - check_shielded_balance(&test, AB_VIEWING_KEY, NAM, 8)?; - check_balance(&test, overflow_addr, NAM, 2)?; - - Ok(()) -} - -/// Test that if the received amount underflows the minimum -/// amount, we error out and refund assets. -#[test] -fn ibc_shielded_recv_middleware_unhappy_flow() -> Result<()> { - let update_genesis = - |mut genesis: templates::All, base_dir: &_| { - genesis.parameters.parameters.epochs_per_year = - epochs_per_year_from_min_duration(1800); - genesis.parameters.ibc_params.default_mint_limit = - Amount::max_signed(); - genesis - .parameters - .ibc_params - .default_per_epoch_throughput_limit = Amount::max_signed(); - setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) - }; - let (ledger, gaia, test, test_gaia) = - run_namada_cosmos(CosmosChainType::Gaia(None), update_genesis)?; - let _bg_ledger = ledger.background(); - let _bg_gaia = gaia.background(); - sleep(5); - - let hermes_dir = setup_hermes(&test, &test_gaia)?; - let port_id_namada = FT_PORT_ID.parse().unwrap(); - let port_id_gaia = FT_PORT_ID.parse().unwrap(); - let (channel_id_namada, channel_id_gaia) = create_channel_with_hermes( - &hermes_dir, - &test, - &test_gaia, - &port_id_namada, - &port_id_gaia, - )?; - - // Start relaying - let hermes = run_hermes(&hermes_dir)?; - let _bg_hermes = hermes.background(); - - let nam_addr = find_address(&test, NAM)?; - let overflow_addr = "tnam1qrqzqa0l0rzzrlr20n487l6n865t8ndv6uhseulq"; - let ibc_denom_on_gaia = format!("transfer/{channel_id_gaia}/{nam_addr}"); - check_balance(&test, ALBERT, NAM, 2_000_000)?; - - let memo_path = gen_ibc_shielding_data( - &test, - AB_PAYMENT_ADDRESS, - &ibc_denom_on_gaia, - 8, - &port_id_namada, - &channel_id_namada, - )?; - let memo = packet_forward_memo( - MASP.to_string().into(), - &PortId::transfer(), - &channel_id_namada, - None, - Some(shielded_recv_memo_value( - &memo_path, - Amount::native_whole(8), - overflow_addr.parse().unwrap(), - )), - ); - transfer( - &test, - ALBERT, - "PacketForwardMiddleware", - NAM, - 7, - Some(ALBERT_KEY), - &PortId::transfer(), - &channel_id_namada, - None, - None, - None, - Some(&memo), - false, - )?; - wait_for_packet_relay(&hermes_dir, &port_id_gaia, &channel_id_gaia, &test)?; - - // Check the token on Namada - check_balance(&test, ALBERT, NAM, 2_000_000)?; - check_shielded_balance(&test, AB_VIEWING_KEY, NAM, 0)?; - check_balance(&test, overflow_addr, NAM, 0)?; - - Ok(()) -} - fn run_namada_cosmos( chain_type: CosmosChainType, mut update_genesis: impl FnMut( @@ -2215,17 +1925,12 @@ fn run_namada_cosmos( let ledger = start_namada_ledger_node_wait_wasm(&test, Some(0), Some(40))?; - let (cosmos, test_cosmos) = setup_and_boot_cosmos(chain_type)?; - - Ok((ledger, cosmos, test, test_cosmos)) -} - -fn setup_and_boot_cosmos( - chain_type: CosmosChainType, -) -> Result<(NamadaCmd, Test)> { + // Cosmos let test_cosmos = setup_cosmos(chain_type)?; let cosmos = run_cosmos(&test_cosmos, true)?; - Ok((cosmos, test_cosmos)) + sleep(5); + + Ok((ledger, cosmos, test, test_cosmos)) } fn create_channel_with_hermes( @@ -2242,7 +1947,6 @@ fn create_channel_with_hermes( } else { FT_CHANNEL_VERSION }; - let args = [ "create", "channel", @@ -2300,7 +2004,7 @@ fn run_cosmos(test: &Test, kill: bool) -> Result { .output() .unwrap(); } - let port_arg = format!("0.0.0.0:{}", chain_type.get_grpc_port_number()); + let port_arg = format!("0.0.0.0:{}", 9090 + chain_type.get_offset()); let args = ["start", "--pruning", "nothing", "--grpc.address", &port_arg]; let cosmos = run_cosmos_cmd(test, args, Some(40))?; Ok(cosmos) @@ -2440,7 +2144,6 @@ fn try_invalid_transfers( None, // the IBC denom can't be parsed when using an invalid port Some(&format!("Invalid IBC denom: {nam_addr}")), - None, false, )?; @@ -2457,7 +2160,6 @@ fn try_invalid_transfers( None, None, Some("IBC token transfer error: context error: `ICS04 Channel error"), - None, false, )?; @@ -2513,7 +2215,6 @@ fn transfer( timeout_sec: Option, shielding_data_path: Option, expected_err: Option<&str>, - ibc_memo: Option<&str>, gen_refund_target: bool, ) -> Result { let rpc = get_actor_rpc(test, Who::Validator(0)); @@ -2541,10 +2242,6 @@ fn transfer( &rpc, ]); - if let Some(ibc_memo) = ibc_memo { - tx_args.extend_from_slice(&["--ibc-memo", ibc_memo]); - } - if let Some(signer) = signer { tx_args.extend_from_slice(&["--signing-keys", signer]); } else { @@ -2935,9 +2632,10 @@ fn transfer_from_cosmos( let port_id = port_id.to_string(); let channel_id = channel_id.to_string(); let amount = format!("{}{}", amount, token.as_ref()); - let chain_type = - CosmosChainType::chain_type(test.net.chain_id.as_str()).unwrap(); - let rpc = format!("tcp://127.0.0.1:{}", chain_type.get_rpc_port_number()); + let offset = CosmosChainType::chain_type(test.net.chain_id.as_str()) + .unwrap() + .get_offset(); + let rpc = format!("tcp://127.0.0.1:6416{offset}"); // If the receiver is a pyament address we want to mask it to the more // general MASP internal address to improve on privacy let receiver = match PaymentAddress::from_str(receiver.as_ref()) { @@ -3096,9 +2794,10 @@ fn check_cosmos_balance( expected_amount: u64, ) -> Result<()> { let addr = find_cosmos_address(test, owner)?; - let chain_type = - CosmosChainType::chain_type(test.net.chain_id.as_str()).unwrap(); - let rpc = format!("tcp://127.0.0.1:{}", chain_type.get_rpc_port_number()); + let offset = CosmosChainType::chain_type(test.net.chain_id.as_str()) + .unwrap() + .get_offset(); + let rpc = format!("tcp://127.0.0.1:6416{offset}"); let args = ["query", "bank", "balances", &addr, "--node", &rpc]; let mut cosmos = run_cosmos_cmd(test, args, Some(40))?; cosmos.exp_string(&format!("amount: \"{expected_amount}\""))?; @@ -3496,756 +3195,26 @@ fn nft_transfer_from_cosmos( Ok(()) } -/// Basic Osmosis test that checks if the chain has been set up correctly. -#[test] -fn osmosis_basic() -> Result<()> { - let (osmosis, test_osmosis) = - setup_and_boot_cosmos(CosmosChainType::Osmosis)?; - - let _bg_osmosis = osmosis.background(); - sleep(5); - - check_cosmos_balance(&test_osmosis, COSMOS_USER, COSMOS_COIN, 1_000)?; - - Ok(()) -} - -#[test] -fn osmosis_xcs() -> Result<()> { - // ========================================================== - // This test requires quite a long setup. Jump to the next - // occurrence of `SETUP DONE` in order to skip all of this - // nonsense. - // ========================================================== - - // Set up a big Cosmos party - let update_genesis = - |mut genesis: templates::All, base_dir: &_| { - genesis.parameters.parameters.epochs_per_year = - epochs_per_year_from_min_duration(1800); - genesis.parameters.ibc_params.default_mint_limit = - Amount::max_signed(); - genesis - .parameters - .ibc_params - .default_per_epoch_throughput_limit = Amount::max_signed(); - setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) - }; - let (namada, gaia, test_namada, test_gaia) = - run_namada_cosmos(CosmosChainType::Gaia(Some(1)), update_genesis)?; - - let (osmosis, test_osmosis) = - setup_and_boot_cosmos(CosmosChainType::Osmosis)?; - - let _bg_osmosis = osmosis.background(); - let _bg_ledger = namada.background(); - let _bg_gaia = gaia.background(); - - // The MC of the party - let osmosis_jones = find_cosmos_address(&test_osmosis, COSMOS_USER)?; - - // Everyone shall take a 5 second nap, partied too hard - // (big up MC Osmosis Jones) - sleep(5); - - // Create hermes relayers with the following config: - // ================================================= - // - // namada -- osmosis -- gaia - // \_____________________/ - - // Set up initial hermes configs - let hermes_gaia_namada = setup_hermes(&test_gaia, &test_namada) - .map_err(|_| eyre!("failed to join thread hermes_gaia_namada"))?; - let hermes_gaia_osmosis = setup_hermes(&test_gaia, &test_osmosis) - .map_err(|_| eyre!("failed to join thread hermes_gaia_osmosis"))?; - let hermes_namada_osmosis = setup_hermes(&test_namada, &test_osmosis) - .map_err(|_| eyre!("failed to join thread hermes_namada_osmosis"))?; - std::thread::sleep(Duration::from_secs(5)); - // Set up channels - let (channel_from_gaia_to_namada, channel_from_namada_to_gaia) = - create_channel_with_hermes( - &hermes_gaia_namada, - &test_gaia, - &test_namada, - &PortId::transfer(), - &PortId::transfer(), - )?; - - // Osmosis currently uses an older version of the Cosmos SDK - // that will error if txs are sent too close together. See - // https://github.com/cosmos/cosmos-sdk/issues/13621 - std::thread::sleep(Duration::from_secs(5)); - let (channel_from_gaia_to_osmosis, channel_from_osmosis_to_gaia) = - create_channel_with_hermes( - &hermes_gaia_osmosis, - &test_gaia, - &test_osmosis, - &PortId::transfer(), - &PortId::transfer(), - )?; - - let (channel_from_namada_to_osmosis, channel_from_osmosis_to_namada) = - create_channel_with_hermes( - &hermes_namada_osmosis, - &test_namada, - &test_osmosis, - &PortId::transfer(), - &PortId::transfer(), - )?; - - // Start relaying - let hermes_1 = run_hermes(&hermes_gaia_namada)?; - let hermes_2 = run_hermes(&hermes_gaia_osmosis)?; - let hermes_3 = run_hermes(&hermes_namada_osmosis)?; - let _bg_hermes_1 = hermes_1.background(); - let _bg_hermes_2 = hermes_2.background(); - let _bg_hermes_3 = hermes_3.background(); - - // Transfer assets to Osmosis, in order to create pools - - // Transfer NAM from Namada - transfer( - &test_namada, - ALBERT, - &osmosis_jones, - NAM, - 500, - Some(ALBERT_KEY), - &PortId::transfer(), - &channel_from_namada_to_osmosis, - None, - None, - None, - None, - false, - )?; - // Transfer Samoleans from Gaia - transfer_from_cosmos( - &test_gaia, - COSMOS_USER, - &osmosis_jones, - COSMOS_COIN, - 500, - &PortId::transfer(), - &channel_from_gaia_to_osmosis, - None, - None, - )?; - - // Related to the issue above. In general, it takes osmosis some time - // to update state. Thus calls to it should be spaced out accordingly. - std::thread::sleep(Duration::from_secs(5)); - - // Check balance of transferred assets on Osmosis - let nam_token_addr = find_address(&test_namada, NAM)?; - check_cosmos_balance( - &test_osmosis, - COSMOS_USER, - format!("transfer/{channel_from_osmosis_to_namada}/{nam_token_addr}"), - 500_000_000, - )?; - - check_cosmos_balance( - &test_osmosis, - COSMOS_USER, - format!("transfer/{channel_from_osmosis_to_gaia}/{COSMOS_COIN}"), - 500, - )?; - - // Set up contracts on Osmosis - let rpc_osmosis = - format!("tcp://{}", get_cosmos_rpc_address(&test_osmosis)); - - const CROSSCHAIN_REGISTRY_CODE_ID: &str = "1"; - const SWAPROUTER_CODE_ID: &str = "2"; - const CROSSCHAIN_SWAPS_CODE_ID: &str = "3"; - - const CROSSCHAIN_REGISTRY_SHA256_HASH: &str = - "3a90b1dc50ba2c63c40298b1645f3a56431d895857cab75f97c5b8266f64e4fa"; - const SWAPROUTER_CODE_SHA256_HASH: &str = - "bd579ce619c16d50118f4a14f98fa1b2724ce11c7de2f8c532a9b2587bd98bbd"; - const CROSSCHAIN_SWAPS_SHA256_HASH: &str = - "87c3c3422e876f117efc5cda6ae30b4c897054148d424815daeb2b3038ec6cfd"; - - // Deploy each contract's wasm bytecode - for wasm in [ - "crosschain_registry.wasm", - "swaprouter.wasm", - "crosschain_swaps.wasm", - ] { - let wasm_path = osmosis_fixtures_dir().join("wasm_bytecode").join(wasm); - let wasm_path_str = wasm_path.to_string_lossy(); - std::thread::sleep(Duration::from_secs(5)); - let args = cosmos_common_args( - "5000000", - None, - test_osmosis.net.chain_id.as_str(), - &rpc_osmosis, - vec!["tx", "wasm", "store", &wasm_path_str], - ); - let mut osmosis_cmd = run_cosmos_cmd(&test_osmosis, args, Some(40))?; - osmosis_cmd.assert_success(); - } - - // Instantiate `crosschain_registry.wasm` - let json = format!(r#"{{"owner":"{osmosis_jones}"}}"#); - std::thread::sleep(Duration::from_secs(5)); - let crosschain_registry_addr = build_contract_addr( - &test_osmosis, - CROSSCHAIN_REGISTRY_SHA256_HASH, - &osmosis_jones, - )?; - std::thread::sleep(Duration::from_secs(5)); - let args = cosmos_common_args( - "2500000", - Some("0.01stake"), - test_osmosis.net.chain_id.as_str(), - &rpc_osmosis, - vec![ - "tx", - "wasm", - "instantiate2", - CROSSCHAIN_REGISTRY_CODE_ID, - &json, - CONTRACT_SALT_HEX, - "--label", - "CrosschainRegistry", - "--no-admin", - "--hex", - ], - ); - let mut osmosis_cmd = run_cosmos_cmd(&test_osmosis, args, Some(40))?; - osmosis_cmd.assert_success(); - - // Instantiate `swaprouter.wasm` - let json = format!(r#"{{"owner":"{osmosis_jones}"}}"#); - std::thread::sleep(Duration::from_secs(10)); - let swaprouter_addr = build_contract_addr( - &test_osmosis, - SWAPROUTER_CODE_SHA256_HASH, - &osmosis_jones, - )?; - std::thread::sleep(Duration::from_secs(10)); - let args = cosmos_common_args( - "250000", - Some("0.01stake"), - test_osmosis.net.chain_id.as_str(), - &rpc_osmosis, - vec![ - "tx", - "wasm", - "instantiate2", - SWAPROUTER_CODE_ID, - &json, - CONTRACT_SALT_HEX, - "--label", - "SwapRouter", - "--no-admin", - "--hex", - ], - ); - let mut osmosis_cmd = run_cosmos_cmd(&test_osmosis, args, Some(40))?; - osmosis_cmd.assert_success(); - - // Instantiate `swaprouter.wasm` - std::thread::sleep(Duration::from_secs(10)); - let json = format!( - r#"{{"governor":"{osmosis_jones}","swap_contract":"{swaprouter_addr}","registry_contract":"{crosschain_registry_addr}"}}"# - ); - let crosschain_swaps_addr = build_contract_addr( - &test_osmosis, - CROSSCHAIN_SWAPS_SHA256_HASH, - &osmosis_jones, - )?; - std::thread::sleep(Duration::from_secs(10)); - let args = cosmos_common_args( - "500000", - Some("0.01stake"), - test_osmosis.net.chain_id.as_str(), - &rpc_osmosis, - vec![ - "tx", - "wasm", - "instantiate2", - CROSSCHAIN_SWAPS_CODE_ID, - &json, - CONTRACT_SALT_HEX, - "--label", - "CrosschainSwaps", - "--no-admin", - "--hex", - ], - ); - - let mut osmosis_cmd = run_cosmos_cmd(&test_osmosis, args, Some(40))?; - osmosis_cmd.assert_success(); - std::thread::sleep(Duration::from_secs(5)); - - // Modify the bech32 prefixes - let msg = serde_json::to_string(&json!({ - "modify_bech32_prefixes": { - "operations": [ - { - "operation": "set", - "chain_name": "namada", - "prefix": "tnam" - }, - { - "operation": "set", - "chain_name": "osmosis", - "prefix": "osmo" - }, - { - "operation": "set", - "chain_name": "gaia", - "prefix": "cosmo" - } - ] - }})) - .unwrap(); - - let args = cosmos_common_args( - "5000000", - Some("0.01stake"), - test_osmosis.net.chain_id.as_str(), - &rpc_osmosis, - vec!["tx", "wasm", "execute", &crosschain_registry_addr, &msg], - ); - let mut osmosis_cmd = run_cosmos_cmd(&test_osmosis, args, Some(40))?; - osmosis_cmd.assert_success(); - std::thread::sleep(Duration::from_secs(5)); - - // Modify the channel chain links - let msg = serde_json::to_string(&json!({ - "modify_chain_channel_links": { - "operations": [ - { - "operation": "set", - "source_chain": "namada", - "destination_chain": "osmosis", - "channel_id": channel_from_namada_to_osmosis - }, - { - "operation": "set", - "source_chain": "osmosis", - "destination_chain": "namada", - "channel_id": channel_from_osmosis_to_namada - }, - { - "operation": "set", - "source_chain": "namada", - "destination_chain": "gaia", - "channel_id": channel_from_namada_to_gaia - }, - { - "operation": "set", - "source_chain": "gaia", - "destination_chain": "namada", - "channel_id": channel_from_gaia_to_namada - }, - { - "operation": "set", - "source_chain": "gaia", - "destination_chain": "osmosis", - "channel_id": channel_from_gaia_to_osmosis - }, - { - "operation": "set", - "source_chain": "osmosis", - "destination_chain": "gaia", - "channel_id": channel_from_osmosis_to_gaia - } - ] - }})) - .unwrap(); - let args = cosmos_common_args( - "5000000", - Some("0.01stake"), - test_osmosis.net.chain_id.as_str(), - &rpc_osmosis, - vec!["tx", "wasm", "execute", &crosschain_registry_addr, &msg], - ); - let mut osmosis_cmd = run_cosmos_cmd(&test_osmosis, args, Some(40))?; - osmosis_cmd.assert_success(); - std::thread::sleep(Duration::from_secs(5)); - - // Enable PFM on gaia and namada - for (chain, token) in [ - ( - "namada", - get_gaia_denom_hash(format!( - "transfer/{channel_from_osmosis_to_namada}/{nam_token_addr}" - )), - ), - ( - "gaia", - get_gaia_denom_hash(format!( - "transfer/{channel_from_osmosis_to_gaia}/{COSMOS_COIN}" - )), - ), - ] { - let msg = format!(r#"{{"propose_pfm": {{"chain": "{chain}"}}}}"#); - let amount = format!("1{token}"); - let args = cosmos_common_args( - "5000000", - Some("0.01stake"), - test_osmosis.net.chain_id.as_str(), - &rpc_osmosis, - vec![ - "tx", - "wasm", - "execute", - &crosschain_registry_addr, - &msg, - "--amount", - &amount, - ], - ); - let mut osmosis_cmd = run_cosmos_cmd(&test_osmosis, args, Some(40))?; - osmosis_cmd.assert_success(); - std::thread::sleep(Duration::from_secs(5)); - } - - wait_for_packet_relay( - &hermes_namada_osmosis, - &PortId::transfer(), - &channel_from_osmosis_to_namada, - &test_osmosis, - )?; - wait_for_packet_relay( - &hermes_gaia_osmosis, - &PortId::transfer(), - &channel_from_osmosis_to_gaia, - &test_osmosis, - )?; - - // Check that the PFM was successfully enabled - // on the contract - for chain in ["namada", "gaia"] { - let msg = - format!(r#"{{"has_packet_forwarding": {{"chain": "{chain}"}}}}"#); - let args = vec![ - "query", - "wasm", - "contract-state", - "smart", - &crosschain_registry_addr, - &msg, - ]; - let mut osmosis_cmd = run_cosmos_cmd(&test_osmosis, args, Some(40))?; - osmosis_cmd.exp_string("data: true")?; - } - - // Create a LP on Osmosis with Samoleans and Nam - create_pool( - &test_osmosis, - &rpc_osmosis, - &[ - ( - &get_gaia_denom_hash(format!( - "transfer/{channel_from_osmosis_to_namada}/\ - {nam_token_addr}" - )), - 100, - ), - ( - &get_gaia_denom_hash(format!( - "transfer/{channel_from_osmosis_to_gaia}/{COSMOS_COIN}" - )), - 100, - ), - ], - )?; - run_cosmos_cmd( - &test_osmosis, - ["query", "poolmanager", "pool", "1"], - Some(40), - )? - .assert_success(); - - // Shield some nam - let rpc_namada = get_actor_rpc(&test_namada, Who::Validator(0)); - - run!( - &test_namada, - Bin::Client, - [ - "shield", - "--source", - BERTHA, - "--target", - AA_PAYMENT_ADDRESS, - "--amount", - "0.000056", - "--token", - NAM, - "--node", - &rpc_namada, - ], - Some(40) - )? - .assert_success(); - - shielded_sync(&test_namada, AA_VIEWING_KEY)?; - - let query_args = vec![ - "balance", - "--owner", - AA_VIEWING_KEY, - "--token", - NAM, - "--node", - &rpc_namada, - ]; - let mut client = run!(&test_namada, Bin::Client, query_args, Some(40))?; - client.exp_string("nam: 0.000056")?; - client.assert_success(); - - // ========================================================== - // SETUP DONE - // ========================================================== - // At this point, we have IBC channels between Osmosis, Gaia - // and Namada. There is a LP with nam and samoleans, that we - // can use to swap between the two assets. Moreover, we have - // shielded some nam tokens. - // ========================================================== - - // We wish to receive samoleans on namada - let output_denom_on_namada = - format!("transfer/{channel_from_namada_to_gaia}/{COSMOS_COIN}"); - - // But on osmosis, we will end up with this token - let output_denom_on_osmosis = get_gaia_denom_hash(format!( - "transfer/{channel_from_osmosis_to_gaia}/{COSMOS_COIN}" - )); - - // Transparently swap samoleans with nam - run!( - &test_namada, - Bin::Client, - [ - "osmosis-swap", - "--osmosis-rest-rpc", - "http://localhost:1317", - "--source", - BERTHA, - "--token", - NAM, - "--amount", - "0.000064", - "--channel-id", - channel_from_namada_to_osmosis.as_ref(), - "--output-denom", - &output_denom_on_namada, - "--local-recovery-addr", - &osmosis_jones, - "--swap-contract", - &crosschain_swaps_addr, - "--minimum-amount", - "1", - "--target", - BERTHA, - "--pool-hop", - &format!("1:{output_denom_on_osmosis}"), - "--node", - &rpc_namada, - ], - Some(40), - )? - .assert_success(); - - wait_for_packet_relay( - &hermes_namada_osmosis, - &PortId::transfer(), - &channel_from_osmosis_to_namada, - &test_osmosis, - )?; - wait_for_packet_relay( - &hermes_gaia_namada, - &PortId::transfer(), - &channel_from_gaia_to_namada, - &test_namada, - )?; - - // Check that the swap worked - // 39 is derived from the uniswap formula: - // floor( 100 - (100*100/(100 + 64)) ) - check_balance( - &test_namada, - BERTHA, - format!("transfer/{channel_from_namada_to_gaia}/{COSMOS_COIN}"), - 39, - )?; - - // Perform a shielded swap of samoleans and nam - run!( - &test_namada, - Bin::Client, - [ - "osmosis-swap", - "--osmosis-rest-rpc", - "http://localhost:1317", - "--source", - AA_VIEWING_KEY, - "--token", - NAM, - "--amount", - "0.000056", - "--channel-id", - channel_from_namada_to_osmosis.as_ref(), - "--output-denom", - &output_denom_on_namada, - "--local-recovery-addr", - &osmosis_jones, - "--swap-contract", - &crosschain_swaps_addr, - "--minimum-amount", - "10", - "--target-pa", - AA_PAYMENT_ADDRESS, - "--overflow-addr", - ALBERT, - "--pool-hop", - &format!("1:{output_denom_on_osmosis}"), - "--gas-payer", - ALBERT_KEY, - "--node", - &rpc_namada, - "--gas-limit", - "500000", - ], - Some(40), - )? - .assert_success(); - - wait_for_packet_relay( - &hermes_namada_osmosis, - &PortId::transfer(), - &channel_from_osmosis_to_namada, - &test_osmosis, - )?; - wait_for_packet_relay( - &hermes_gaia_namada, - &PortId::transfer(), - &channel_from_gaia_to_namada, - &test_namada, - )?; - - // Check that the minimum amount got shielded - check_shielded_balance( - &test_namada, - AA_VIEWING_KEY, - &output_denom_on_namada, - 10, - )?; - // 5 is derived from the uniswap formula: - // floor( 61 - ( 164 * 61 / (164 + 56) ) ) minus - // the minimum amount (10) which was shielded - check_balance(&test_namada, ALBERT, &output_denom_on_namada, 5)?; - - Ok(()) -} - -fn cosmos_common_args<'a>( - gas: &'a str, - gas_price: Option<&'a str>, - chain_id: &'a str, - rpc: &'a str, - mut args: Vec<&'a str>, -) -> Vec<&'a str> { - args.extend_from_slice(&[ - "--from", - COSMOS_USER, - "--gas", - gas, - "--gas-prices", - gas_price.unwrap_or("0.01stake"), - "--node", - rpc, - "--keyring-backend", - "test", - "--chain-id", - chain_id, - "--yes", - ]); - args -} - -fn build_contract_addr( - test: &Test, - wasm_bytecode_hash: &str, - creator_addr: &str, -) -> Result { - let osmosis_home = test.test_dir.as_ref().join("osmosis"); - let args = [ - "--home", - osmosis_home.to_str().unwrap(), - "query", - "wasm", - "build-address", - wasm_bytecode_hash, - creator_addr, - CONTRACT_SALT_HEX, - ]; - let mut cosmos = run_cosmos_cmd_homeless(test, args, Some(40))?; - let (_, matched) = cosmos.exp_regex("address: .*\n")?; - let mut parts = matched.split(':'); - parts.next().unwrap(); - Ok(parts.next().unwrap().trim().to_string()) -} - -/// Create a liquidity pool on osmosis. -/// All tokens will be 1:1 swappable in the provided -/// denoms. -fn create_pool( - test: &Test, - rpc: &str, - denoms_and_deposits: &[(&str, u64)], -) -> Result<()> { - let json_path = test.test_dir.path().join("pool.json"); - let mut weights = - denoms_and_deposits - .iter() - .fold(String::new(), |mut acc, (d, _)| { - acc.push_str(&format!("1{d},")); - acc - }); - weights.pop(); - let mut init_deposits = - denoms_and_deposits - .iter() - .fold(String::new(), |mut acc, (d, a)| { - acc.push_str(&format!("{a}{d},")); - acc - }); - init_deposits.pop(); - let pool_json = json!({ - "weights": weights, - "initial-deposit": init_deposits, - "swap-fee": "0.001", - "exit-fee": "0.000" - }); - let json_file = File::create(&json_path)?; - serde_json::to_writer(json_file, &pool_json)?; - let json_path = json_path.to_string_lossy(); - let args = cosmos_common_args( - "2500000", - Some("0.01stake"), - "osmosis", - rpc, - vec![ - "tx", - "poolmanager", - "create-pool", - "--pool-file", - &json_path, - ], - ); - let mut osmosis_cmd = run_cosmos_cmd(test, args, Some(40))?; - osmosis_cmd.assert_success(); - std::thread::sleep(Duration::from_secs(5)); - Ok(()) +/// Create a packet forward memo and serialize it +fn packet_forward_memo( + receiver: Signer, + port_id: &PortId, + channel_id: &ChannelId, + timeout: Option, +) -> String { + serde_json::to_string(&ibc_middleware_packet_forward::PacketMetadata { + forward: ForwardMetadata { + receiver, + port: port_id.clone(), + channel: channel_id.clone(), + timeout: timeout.map(|t| { + ibc_middleware_packet_forward::Duration::from_dur( + dur::Duration::from_std(t), + ) + }), + retries: Some(0), + next: None, + }, + }) + .expect("Test failed") } - -const CONTRACT_SALT_HEX: &str = "01020304"; diff --git a/crates/tests/src/e2e/setup.rs b/crates/tests/src/e2e/setup.rs index 4eec9b69be..d0bdb14f80 100644 --- a/crates/tests/src/e2e/setup.rs +++ b/crates/tests/src/e2e/setup.rs @@ -42,8 +42,8 @@ use rand::Rng; use tempfile::{tempdir, tempdir_in, TempDir}; use crate::e2e::helpers::{ - find_cosmos_address, generate_bin_command, get_cosmos_rpc_address, - make_hermes_config, update_cosmos_config, + find_cosmos_address, generate_bin_command, make_hermes_config, + update_cosmos_config, }; /// For `color_eyre::install`, which fails if called more than once in the same @@ -844,22 +844,6 @@ pub fn working_dir() -> PathBuf { working_dir } -/// Return the path to all test fixture. -pub fn fixtures_dir() -> PathBuf { - let mut dir = working_dir(); - dir.push("crates"); - dir.push("tests"); - dir.push("fixtures"); - dir -} - -/// Return the path to all osmosis fixture. -pub fn osmosis_fixtures_dir() -> PathBuf { - let mut dir = fixtures_dir(); - dir.push("osmosis_data"); - dir -} - /// A command under test pub struct NamadaCmd { pub session: Session>, @@ -1259,126 +1243,31 @@ pub fn setup_hermes(test_a: &Test, test_b: &Test) -> Result { let hermes_dir = TestDir::new(); println!("\n{}", "Setting up Hermes".underline().green(),); - let chain_name_a = - CosmosChainType::chain_type(test_a.net.chain_id.as_str()) - .map(|c| c.chain_id()) - .ok(); - let chain_name_b = - CosmosChainType::chain_type(test_b.net.chain_id.as_str()) - .map(|c| c.chain_id()) - .ok(); - let relayer = chain_name_a - .zip(chain_name_b) - .map(|(a, b)| format!("{a}_{b}_relayer")); - make_hermes_config( - &hermes_dir, - test_a, - test_b, - relayer.as_ref().map(|s| s.as_ref()), - )?; + + make_hermes_config(&hermes_dir, test_a, test_b)?; for test in [test_a, test_b] { let chain_id = test.net.chain_id.as_str(); let chain_dir = test.test_dir.as_ref().join(chain_id); - match CosmosChainType::chain_type(chain_id) { - Ok(_) => { - if let Some(relayer) = relayer.as_ref() { - // we create a new relayer for each ibc connection between - // to non-Namada chains - let key_file = - chain_dir.join(format!("{relayer}_seed.json")); - let args = [ - "keys", - "add", - relayer, - "--keyring-backend", - "test", - "--output", - "json", - ]; - let mut cosmos = run_cosmos_cmd(test, args, Some(10))?; - let result = cosmos.exp_string("\n")?; - let mut file = File::create(&key_file).unwrap(); - file.write_all(result.as_bytes()).map_err(|e| { - eyre!(format!( - "Writing a Cosmos key file failed: {}", - e - )) - })?; - - let account = find_cosmos_address(test, relayer)?; - // Add tokens to the new relayer account - let args = [ - "tx", - "bank", - "send", - constants::COSMOS_RELAYER, - &account, - "500000000stake", - "--from", - constants::COSMOS_RELAYER, - "--gas", - "250000", - "--gas-prices", - "0.01stake", - "--node", - &format!("http://{}", get_cosmos_rpc_address(test)), - "--keyring-backend", - "test", - "--chain-id", - chain_id, - "--yes", - ]; - - let mut cosmos = run_cosmos_cmd(test, args, Some(10))?; - cosmos.assert_success(); - - // add to hermes - let args = [ - "keys", - "add", - "--chain", - chain_id, - "--key-file", - &key_file.to_string_lossy(), - "--key-name", - relayer, - ]; - let mut hermes = - run_hermes_cmd(&hermes_dir, args, Some(20))?; - hermes.assert_success(); - } else { - let key_file_path = chain_dir.join(format!( - "{}_seed.json", - constants::COSMOS_RELAYER - )); - let args = [ - "keys", - "add", - "--chain", - chain_id, - "--key-file", - &key_file_path.to_string_lossy(), - ]; - let mut hermes = - run_hermes_cmd(&hermes_dir, args, Some(20))?; - hermes.assert_success(); - } - } - Err(_) => { - let key_file_path = wallet::wallet_file(&chain_dir); - let args = [ - "keys", - "add", - "--chain", - chain_id, - "--key-file", - &key_file_path.to_string_lossy(), - ]; - let mut hermes = run_hermes_cmd(&hermes_dir, args, Some(20))?; - hermes.assert_success(); - } + let key_file_path = match CosmosChainType::chain_type(chain_id) { + Ok(_) => chain_dir + .join(format!("{}_seed.json", constants::COSMOS_RELAYER)), + Err(_) => wallet::wallet_file(chain_dir), }; + let args = [ + "keys", + "add", + // TODO: this overwrite is required because hermes keys are pulled + // from the namada chain dir... however, ideally we would store the + // `wallet.toml` file under hermes' own dir + "--overwrite", + "--chain", + chain_id, + "--key-file", + &key_file_path.to_string_lossy(), + ]; + let mut hermes = run_hermes_cmd(&hermes_dir, args, Some(20))?; + hermes.assert_success(); } Ok(hermes_dir) @@ -1452,46 +1341,9 @@ where pub enum CosmosChainType { Gaia(Option), CosmWasm, - Osmosis, } impl CosmosChainType { - fn genesis_cmd_args<'a>(&self, mut args: Vec<&'a str>) -> Vec<&'a str> { - if !matches!(self, CosmosChainType::Osmosis) { - args.insert(0, "genesis"); - } - args - } - - fn add_genesis_account_args<'a>( - &self, - account: &'a str, - coins: &'a str, - ) -> Vec<&'a str> { - self.genesis_cmd_args(vec!["add-genesis-account", account, coins]) - } - - fn gentx_args<'a>( - &self, - account: &'a str, - coins: &'a str, - chain_id: &'a str, - ) -> Vec<&'a str> { - self.genesis_cmd_args(vec![ - "gentx", - account, - coins, - "--keyring-backend", - "test", - "--chain-id", - chain_id, - ]) - } - - fn collect_gentxs_args<'a>(&self) -> Vec<&'a str> { - self.genesis_cmd_args(vec!["collect-gentxs"]) - } - pub fn chain_id(&self) -> String { match self { Self::Gaia(Some(suffix)) => { @@ -1499,7 +1351,6 @@ impl CosmosChainType { } Self::Gaia(_) => constants::GAIA_CHAIN_ID.to_string(), Self::CosmWasm => constants::COSMWASM_CHAIN_ID.to_string(), - Self::Osmosis => constants::OSMOSIS_CHAIN_ID.to_string(), } } @@ -1507,7 +1358,6 @@ impl CosmosChainType { match self { Self::Gaia(_) => "gaiad", Self::CosmWasm => "wasmd", - Self::Osmosis => "osmosisd", } } @@ -1515,9 +1365,6 @@ impl CosmosChainType { if chain_id == constants::COSMWASM_CHAIN_ID { return Ok(Self::CosmWasm); } - if chain_id == constants::OSMOSIS_CHAIN_ID { - return Ok(Self::Osmosis); - } match chain_id.strip_prefix(constants::GAIA_CHAIN_ID) { Some("") => Ok(Self::Gaia(None)), Some(suffix) => { @@ -1533,29 +1380,13 @@ impl CosmosChainType { match self { Self::Gaia(_) => "cosmos", Self::CosmWasm => "wasm", - Self::Osmosis => "osmo", } } - pub fn get_p2p_port_number(&self) -> u64 { - 10_000 + self.get_offset() - } - - pub fn get_rpc_port_number(&self) -> u64 { - 20_000 + self.get_offset() - } - - pub fn get_grpc_port_number(&self) -> u64 { - 30_000 + self.get_offset() - } - - fn get_offset(&self) -> u64 { - // NB: ensure none of these ever conflict + pub fn get_offset(&self) -> u64 { match self { - Self::CosmWasm => 0, - Self::Osmosis => 1, - Self::Gaia(None) => 2, - Self::Gaia(Some(off)) => 3 + *off, + Self::Gaia(Some(off)) => *off, + _ => 0, } } } @@ -1606,42 +1437,47 @@ pub fn setup_cosmos(chain_type: CosmosChainType) -> Result { // Add tokens to a user account let account = find_cosmos_address(&test, constants::COSMOS_USER)?; - let args = if let CosmosChainType::Osmosis = chain_type { - chain_type.add_genesis_account_args( - &account, - "100000000stake,1000samoleans, 10000000000uosmo", - ) - } else { - chain_type - .add_genesis_account_args(&account, "100000000stake,1000samoleans") - }; + let args = [ + "genesis", + "add-genesis-account", + &account, + "100000000stake,1000samoleans", + ]; let mut cosmos = run_cosmos_cmd(&test, args, Some(10))?; cosmos.assert_success(); // Add the stake token to the relayer let account = find_cosmos_address(&test, constants::COSMOS_RELAYER)?; - let args = - chain_type.add_genesis_account_args(&account, "10000000000stake"); + let args = ["genesis", "add-genesis-account", &account, "10000stake"]; let mut cosmos = run_cosmos_cmd(&test, args, Some(10))?; cosmos.assert_success(); // Add the stake token to the validator let validator = find_cosmos_address(&test, constants::COSMOS_VALIDATOR)?; - let args = - chain_type.add_genesis_account_args(&validator, "200000000000stake"); + let args = [ + "genesis", + "add-genesis-account", + &validator, + "200000000000stake", + ]; let mut cosmos = run_cosmos_cmd(&test, args, Some(10))?; cosmos.assert_success(); // stake - let args = chain_type.gentx_args( + let args = [ + "genesis", + "gentx", constants::COSMOS_VALIDATOR, "100000000000stake", + "--keyring-backend", + "test", + "--chain-id", &chain_id, - ); + ]; let mut cosmos = run_cosmos_cmd(&test, args, Some(10))?; cosmos.assert_success(); - let args = chain_type.collect_gentxs_args(); + let args = ["genesis", "collect-gentxs"]; let mut cosmos = run_cosmos_cmd(&test, args, Some(10))?; cosmos.assert_success(); @@ -1650,67 +1486,6 @@ pub fn setup_cosmos(chain_type: CosmosChainType) -> Result { Ok(test) } -pub fn run_cosmos_cmd_homeless( - test: &Test, - args: I, - timeout_sec: Option, -) -> Result -where - I: IntoIterator, - S: AsRef, -{ - let chain_id = test.net.chain_id.as_str(); - let chain_type = CosmosChainType::chain_type(chain_id)?; - let mut run_cmd = Command::new(chain_type.command_path()); - run_cmd.args(args); - - let args: String = - run_cmd.get_args().map(|s| s.to_string_lossy()).join(" "); - let cmd_str = - format!("{} {}", run_cmd.get_program().to_string_lossy(), args); - - let session = Session::spawn(run_cmd).map_err(|e| { - eyre!( - "\n\n{}: {}\n{}: {}", - "Failed to run Cosmos command".underline().red(), - cmd_str, - "Error".underline().red(), - e - ) - })?; - - let log_path = { - let mut rng = rand::thread_rng(); - let log_dir = test.get_base_dir(Who::NonValidator).join("logs"); - std::fs::create_dir_all(&log_dir)?; - log_dir.join(format!( - "{}-cosmos-{}.log", - SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_micros(), - rng.gen::() - )) - }; - let logger = OpenOptions::new() - .write(true) - .create_new(true) - .open(&log_path)?; - let mut session = expectrl::session::log(session, logger).unwrap(); - - session.set_expect_timeout(timeout_sec.map(std::time::Duration::from_secs)); - - let cmd_process = NamadaCmd { - session, - cmd_str, - log_path, - }; - - println!("{}:\n{}", "> Running".underline().green(), &cmd_process); - - Ok(cmd_process) -} - pub fn run_cosmos_cmd( test: &Test, args: I, @@ -1826,10 +1601,10 @@ pub mod constants { pub const APFEL: &str = "Apfel"; pub const KARTOFFEL: &str = "Kartoffel"; - // Gaia or CosmWasm or Osmosis + // Gaia or CosmWasm pub const GAIA_CHAIN_ID: &str = "gaia"; - pub const OSMOSIS_CHAIN_ID: &str = "osmosis"; pub const COSMWASM_CHAIN_ID: &str = "cosmwasm"; + pub const COSMOS_RPC: &str = "127.0.0.1:64160"; pub const COSMOS_USER: &str = "user"; pub const COSMOS_RELAYER: &str = "relayer"; pub const COSMOS_VALIDATOR: &str = "validator"; diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 1e6a4389fb..6400887db7 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -3076,90 +3076,10 @@ dependencies = [ "syn 2.0.96", ] -[[package]] -name = "ibc-middleware-module" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=module/v0.1.0#3d3b436f7c58000c7498d68e88c15a955433a619" -dependencies = [ - "ibc-core-channel-types", - "ibc-core-host-types", - "ibc-core-router", - "ibc-core-router-types", - "ibc-primitives", -] - -[[package]] -name = "ibc-middleware-module" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=orm/v0.4.0#8d341de14ff5e2a637699796cffbf0fbbaee001f" -dependencies = [ - "ibc-core-channel-types", - "ibc-core-host-types", - "ibc-core-router", - "ibc-core-router-types", - "ibc-primitives", -] - -[[package]] -name = "ibc-middleware-module" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.9.0#3d3b436f7c58000c7498d68e88c15a955433a619" -dependencies = [ - "ibc-core-channel-types", - "ibc-core-host-types", - "ibc-core-router", - "ibc-core-router-types", - "ibc-primitives", -] - -[[package]] -name = "ibc-middleware-module-macros" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=module-macros/v0.1.0#3d3b436f7c58000c7498d68e88c15a955433a619" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "ibc-middleware-module-macros" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=orm/v0.4.0#8d341de14ff5e2a637699796cffbf0fbbaee001f" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "ibc-middleware-module-macros" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.9.0#3d3b436f7c58000c7498d68e88c15a955433a619" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "ibc-middleware-overflow-receive" -version = "0.4.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=orm/v0.4.0#8d341de14ff5e2a637699796cffbf0fbbaee001f" -dependencies = [ - "ibc-app-transfer-types", - "ibc-core-channel-types", - "ibc-core-host-types", - "ibc-core-router", - "ibc-core-router-types", - "ibc-middleware-module 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=orm/v0.4.0)", - "ibc-middleware-module-macros 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=orm/v0.4.0)", - "ibc-primitives", - "serde", - "serde_json", -] - [[package]] name = "ibc-middleware-packet-forward" -version = "0.9.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.9.0#3d3b436f7c58000c7498d68e88c15a955433a619" +version = "0.8.0" +source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.8.0#9c4a410063df8562c726c76009ff08b4e5a1894a" dependencies = [ "borsh", "dur", @@ -3170,8 +3090,6 @@ dependencies = [ "ibc-core-host-types", "ibc-core-router", "ibc-core-router-types", - "ibc-middleware-module 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.9.0)", - "ibc-middleware-module-macros 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.9.0)", "ibc-primitives", "serde", "serde_json", @@ -4073,9 +3991,6 @@ dependencies = [ "dur", "ibc", "ibc-derive", - "ibc-middleware-module 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=module/v0.1.0)", - "ibc-middleware-module-macros 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=module-macros/v0.1.0)", - "ibc-middleware-overflow-receive", "ibc-middleware-packet-forward", "ibc-testkit", "ics23", @@ -4187,7 +4102,6 @@ name = "namada_sdk" version = "0.46.1" dependencies = [ "async-trait", - "bech32 0.8.1", "bimap", "borsh", "circular-queue", @@ -5404,9 +5318,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.38" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] diff --git a/wasm_for_tests/Cargo.lock b/wasm_for_tests/Cargo.lock index f6e7a4aa12..f993f3e33b 100644 --- a/wasm_for_tests/Cargo.lock +++ b/wasm_for_tests/Cargo.lock @@ -1710,90 +1710,10 @@ dependencies = [ "syn 2.0.96", ] -[[package]] -name = "ibc-middleware-module" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=module/v0.1.0#3d3b436f7c58000c7498d68e88c15a955433a619" -dependencies = [ - "ibc-core-channel-types", - "ibc-core-host-types", - "ibc-core-router", - "ibc-core-router-types", - "ibc-primitives", -] - -[[package]] -name = "ibc-middleware-module" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=orm/v0.4.0#8d341de14ff5e2a637699796cffbf0fbbaee001f" -dependencies = [ - "ibc-core-channel-types", - "ibc-core-host-types", - "ibc-core-router", - "ibc-core-router-types", - "ibc-primitives", -] - -[[package]] -name = "ibc-middleware-module" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.9.0#3d3b436f7c58000c7498d68e88c15a955433a619" -dependencies = [ - "ibc-core-channel-types", - "ibc-core-host-types", - "ibc-core-router", - "ibc-core-router-types", - "ibc-primitives", -] - -[[package]] -name = "ibc-middleware-module-macros" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=module-macros/v0.1.0#3d3b436f7c58000c7498d68e88c15a955433a619" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "ibc-middleware-module-macros" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=orm/v0.4.0#8d341de14ff5e2a637699796cffbf0fbbaee001f" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "ibc-middleware-module-macros" -version = "0.1.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.9.0#3d3b436f7c58000c7498d68e88c15a955433a619" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "ibc-middleware-overflow-receive" -version = "0.4.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=orm/v0.4.0#8d341de14ff5e2a637699796cffbf0fbbaee001f" -dependencies = [ - "ibc-app-transfer-types", - "ibc-core-channel-types", - "ibc-core-host-types", - "ibc-core-router", - "ibc-core-router-types", - "ibc-middleware-module 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=orm/v0.4.0)", - "ibc-middleware-module-macros 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=orm/v0.4.0)", - "ibc-primitives", - "serde", - "serde_json", -] - [[package]] name = "ibc-middleware-packet-forward" -version = "0.9.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.9.0#3d3b436f7c58000c7498d68e88c15a955433a619" +version = "0.8.0" +source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.8.0#9c4a410063df8562c726c76009ff08b4e5a1894a" dependencies = [ "borsh", "dur", @@ -1804,8 +1724,6 @@ dependencies = [ "ibc-core-host-types", "ibc-core-router", "ibc-core-router-types", - "ibc-middleware-module 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.9.0)", - "ibc-middleware-module-macros 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.9.0)", "ibc-primitives", "serde", "serde_json", @@ -2445,9 +2363,6 @@ dependencies = [ "dur", "ibc", "ibc-derive", - "ibc-middleware-module 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=module/v0.1.0)", - "ibc-middleware-module-macros 0.1.0 (git+https://github.com/heliaxdev/ibc-middleware?tag=module-macros/v0.1.0)", - "ibc-middleware-overflow-receive", "ibc-middleware-packet-forward", "ics23", "konst", @@ -3307,9 +3222,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.38" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ]