From 48507e256ef91a89b0a7da1fb88cbb1a5ad5ebea Mon Sep 17 00:00:00 2001 From: Christian Gorenflo Date: Thu, 21 Nov 2024 16:03:34 -0500 Subject: [PATCH 1/3] feat(upgrader): add generalized atomic upgrade and migration capabilities (#77) --- Cargo.lock | 8 + contracts/axelar-gateway/src/contract.rs | 71 +++- contracts/axelar-gateway/src/error.rs | 1 + contracts/axelar-gateway/src/interface.rs | 12 +- contracts/axelar-gateway/src/storage_types.rs | 1 + contracts/upgrader/Cargo.toml | 17 + contracts/upgrader/src/contract.rs | 312 ++++++++++++++++++ contracts/upgrader/src/error.rs | 8 + contracts/upgrader/src/lib.rs | 6 + contracts/upgrader/src/testdata/dummy.wasm | Bin 0 -> 1442 bytes packages/axelar-soroban-std/src/lib.rs | 5 +- packages/axelar-soroban-std/src/traits.rs | 30 +- packages/axelar-soroban-std/src/upgrade.rs | 11 + 13 files changed, 451 insertions(+), 31 deletions(-) create mode 100644 contracts/upgrader/Cargo.toml create mode 100644 contracts/upgrader/src/contract.rs create mode 100644 contracts/upgrader/src/error.rs create mode 100644 contracts/upgrader/src/lib.rs create mode 100755 contracts/upgrader/src/testdata/dummy.wasm create mode 100644 packages/axelar-soroban-std/src/upgrade.rs diff --git a/Cargo.lock b/Cargo.lock index 5758aa8d..8e88f073 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1484,6 +1484,14 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "upgrader" +version = "0.1.0" +dependencies = [ + "axelar-soroban-std", + "soroban-sdk", +] + [[package]] name = "upon" version = "0.8.1" diff --git a/contracts/axelar-gateway/src/contract.rs b/contracts/axelar-gateway/src/contract.rs index 47da88c5..96ed5063 100644 --- a/contracts/axelar-gateway/src/contract.rs +++ b/contracts/axelar-gateway/src/contract.rs @@ -1,13 +1,13 @@ use crate::error::ContractError; +use crate::interface::AxelarGatewayInterface; +use crate::storage_types::{DataKey, MessageApprovalKey, MessageApprovalValue}; use crate::types::{CommandType, Message, Proof, WeightedSigners}; +use crate::{auth, event}; use axelar_soroban_std::ensure; +pub use axelar_soroban_std::UpgradeableInterface; use soroban_sdk::xdr::ToXdr; use soroban_sdk::{contract, contractimpl, Address, Bytes, BytesN, Env, String, Vec}; -use crate::interface::AxelarGatewayInterface; -use crate::storage_types::{DataKey, MessageApprovalKey, MessageApprovalValue}; -use crate::{auth, event}; - const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); /// Parameters for extending the contract instance and its instance storage. @@ -22,6 +22,24 @@ const INSTANCE_TTL_EXTEND_TO: u32 = 60 * LEDGERS_PER_DAY; #[contract] pub struct AxelarGateway; +#[contractimpl] +impl UpgradeableInterface for AxelarGateway { + type Error = ContractError; + + fn version(env: Env) -> String { + String::from_str(&env, CONTRACT_VERSION) + } + + fn upgrade(env: Env, new_wasm_hash: BytesN<32>) -> Result<(), ContractError> { + Self::owner(&env).require_auth(); + + env.deployer().update_current_contract_wasm(new_wasm_hash); + Self::start_migration(&env); + + Ok(()) + } +} + #[contractimpl] impl AxelarGateway { /// Initialize the gateway @@ -47,6 +65,18 @@ impl AxelarGateway { Ok(()) } + + /// Migrate the contract state after upgrading the contract code. the migration_data type can be adjusted as needed. + pub fn migrate(env: Env, migration_data: ()) -> Result<(), ContractError> { + // This function should not get modified. + // Custom migration logic that changes from version to version should be added in the run_migration function + Self::ensure_is_migrating(&env)?; + + Self::run_migration(&env, migration_data); + Self::complete_migration(&env); + + Ok(()) + } } #[contractimpl] @@ -223,16 +253,6 @@ impl AxelarGatewayInterface for AxelarGateway { auth::epoch(env) } - fn version(env: &Env) -> String { - String::from_str(env, CONTRACT_VERSION) - } - - fn upgrade(env: Env, new_wasm_hash: BytesN<32>) { - Self::owner(&env).require_auth(); - - env.deployer().update_current_contract_wasm(new_wasm_hash); - } - fn transfer_ownership(env: Env, new_owner: Address) { let owner: Address = Self::owner(&env); owner.require_auth(); @@ -290,4 +310,27 @@ impl AxelarGateway { .instance() .extend_ttl(INSTANCE_TTL_THRESHOLD, INSTANCE_TTL_EXTEND_TO); } + + fn ensure_is_migrating(env: &Env) -> Result<(), ContractError> { + let is_migrating = env + .storage() + .instance() + .get::(&DataKey::Migrating) + .unwrap_or(false); + + ensure!(is_migrating, ContractError::MigrationNotAllowed); + Ok(()) + } + + fn start_migration(env: &Env) { + env.storage().instance().set(&DataKey::Migrating, &true); + } + + // Modify this function to add migration logic + #[allow(clippy::missing_const_for_fn)] // exclude no-op implementations from this lint + fn run_migration(_env: &Env, _migration_data: ()) {} + + fn complete_migration(env: &Env) { + env.storage().instance().set(&DataKey::Migrating, &false); + } } diff --git a/contracts/axelar-gateway/src/error.rs b/contracts/axelar-gateway/src/error.rs index 8269b498..e863bb1c 100644 --- a/contracts/axelar-gateway/src/error.rs +++ b/contracts/axelar-gateway/src/error.rs @@ -20,4 +20,5 @@ pub enum ContractError { EmptyMessages = 12, // Executable NotApproved = 13, + MigrationNotAllowed = 14, } diff --git a/contracts/axelar-gateway/src/interface.rs b/contracts/axelar-gateway/src/interface.rs index 635d6e03..04487326 100644 --- a/contracts/axelar-gateway/src/interface.rs +++ b/contracts/axelar-gateway/src/interface.rs @@ -1,12 +1,12 @@ -use soroban_sdk::{contractclient, Address, Bytes, BytesN, Env, String, Vec}; - use crate::{ error::ContractError, types::{Message, Proof, WeightedSigners}, }; +use axelar_soroban_std::UpgradeableInterface; +use soroban_sdk::{contractclient, Address, Bytes, BytesN, Env, String, Vec}; #[contractclient(name = "AxelarGatewayClient")] -pub trait AxelarGatewayInterface { +pub trait AxelarGatewayInterface: UpgradeableInterface { /// Sends a message to the specified destination chain and contarct address with a given payload. /// /// This function is the entry point for general message passing between chains. @@ -76,12 +76,6 @@ pub trait AxelarGatewayInterface { /// Returns the epoch of the gateway. fn epoch(env: &Env) -> u64; - /// Returns the version of the gateway. - fn version(env: &Env) -> String; - - /// Upgrades the gateway to a new wasm hash. - fn upgrade(env: Env, new_wasm_hash: BytesN<32>); - /// Transfers ownership of the gateway to a new address. fn transfer_ownership(env: Env, new_owner: Address); diff --git a/contracts/axelar-gateway/src/storage_types.rs b/contracts/axelar-gateway/src/storage_types.rs index 506cff25..bca6d200 100644 --- a/contracts/axelar-gateway/src/storage_types.rs +++ b/contracts/axelar-gateway/src/storage_types.rs @@ -22,6 +22,7 @@ pub enum DataKey { Owner, Operator, MessageApproval(MessageApprovalKey), + Migrating, /// Auth Module PreviousSignerRetention, DomainSeparator, diff --git a/contracts/upgrader/Cargo.toml b/contracts/upgrader/Cargo.toml new file mode 100644 index 00000000..5a76279e --- /dev/null +++ b/contracts/upgrader/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "upgrader" +version = "0.1.0" +edition = { workspace = true } + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +axelar-soroban-std = { workspace = true } +soroban-sdk = { workspace = true } + +[dev-dependencies] +soroban-sdk = { workspace = true, features = ["testutils"] } + +[lints] +workspace = true diff --git a/contracts/upgrader/src/contract.rs b/contracts/upgrader/src/contract.rs new file mode 100644 index 00000000..e06e29e9 --- /dev/null +++ b/contracts/upgrader/src/contract.rs @@ -0,0 +1,312 @@ +#![allow(dead_code)] + +use crate::error::ContractError; +use axelar_soroban_std::traits::ThenOk; +use soroban_sdk::{contract, contractimpl, Address, BytesN, Env, String, Symbol, Val}; + +const MIGRATE: &str = "migrate"; +const UPGRADE: &str = "upgrade"; +const VERSION: &str = "version"; + +#[contract] +pub struct Upgrader; + +#[contractimpl] +impl Upgrader { + pub fn __constructor(_env: Env) {} + + pub fn upgrade( + env: Env, + contract_address: Address, + new_version: String, + new_wasm_hash: BytesN<32>, + migration_data: soroban_sdk::Vec, + ) -> Result<(), ContractError> { + ensure_new_version_is_different(&env, &contract_address, &new_version)?; + + // it's safe to map the true return value of the upgrade and migrate functions to (), + // because we don't care about it, and in case of failure the contract will panic anyway + env.invoke_contract::<()>( + &contract_address, + &Symbol::new(&env, UPGRADE), + soroban_sdk::vec![&env, new_wasm_hash.into()], + ); + + env.invoke_contract::<()>( + &contract_address, + &Symbol::new(&env, MIGRATE), + migration_data, + ); + + ensure_new_version_matches_expected(&env, &contract_address, &new_version) + } +} + +fn ensure_new_version_is_different( + env: &Env, + contract_address: &Address, + new_version: &String, +) -> Result<(), ContractError> { + let no_match = current_version(env, contract_address) != *new_version; + no_match.then_ok((), ContractError::SameVersion) +} + +fn ensure_new_version_matches_expected( + env: &Env, + contract_address: &Address, + new_version: &String, +) -> Result<(), ContractError> { + let versions_match = current_version(env, contract_address) == *new_version; + versions_match.then_ok((), ContractError::UnexpectedNewVersion) +} + +fn current_version(env: &Env, contract_address: &Address) -> String { + env.invoke_contract( + contract_address, + &Symbol::new(env, VERSION), + soroban_sdk::vec![env], + ) +} + +#[cfg(test)] +mod tests { + use crate::contract::{Upgrader, UpgraderClient, MIGRATE, UPGRADE, VERSION}; + use axelar_soroban_std::UpgradeableInterface; + use soroban_sdk::testutils::{Address as _, MockAuth, MockAuthInvoke}; + use soroban_sdk::{contract, contracterror, contractimpl, contracttype, Address, Symbol}; + use soroban_sdk::{BytesN, Env, String}; + + /// A simple contract to test the upgrader + #[contract] + struct DummyContract; + + /// Dummy contract logic before upgrade + #[contractimpl] + impl UpgradeableInterface for DummyContract { + type Error = ContractError; + + fn version(env: Env) -> String { + String::from_str(&env, "0.1.0") + } + + fn upgrade(env: Env, new_wasm_hash: BytesN<32>) -> Result<(), ContractError> { + Self::owner(&env).require_auth(); + + env.deployer().update_current_contract_wasm(new_wasm_hash); + Ok(()) + } + } + + #[contractimpl] + impl DummyContract { + pub fn __constructor(env: Env, owner: Address) { + env.storage().instance().set(&DataKey::Owner, &owner) + } + + fn owner(env: &Env) -> Address { + env.storage().instance().get(&DataKey::Owner).unwrap() + } + } + + #[contracttype] + enum DataKey { + Data, + Owner, + } + + #[contracterror] + enum ContractError { + SomeFailure = 1, + } + + /// Dummy contract logic after upgrade is loaded into WASM_AFTER_UPGRADE + /// + /// #[contractimpl] + /// impl UpgradeableInterface for DummyContract { + /// type Error = ContractError; + /// + /// fn version(env: Env) -> String { + /// String::from_str(&env, "0.2.0") + /// } + /// + /// fn upgrade(env: Env, new_wasm_hash: BytesN<32>) -> Result<(), ContractError> { + /// Self::owner(&env).require_auth(); + /// + /// env.deployer().update_current_contract_wasm(new_wasm_hash); + /// Ok(()) + /// } + /// } + /// + /// #[contractimpl] + /// impl DummyContract { + /// pub fn migrate(env: Env, migration_data: String) { + /// Self::owner(&env).require_auth(); + /// + /// env.storage() + /// .instance() + /// .set(&DataKey::Data, &migration_data); + /// } + /// + /// fn owner(env: &Env) -> Address { + /// env.storage().instance().get(&DataKey::Owner).unwrap() + /// } + /// } + const WASM_AFTER_UPGRADE: &[u8] = include_bytes!("testdata/dummy.wasm"); + + #[test] + fn upgrade_and_migrate_are_atomic() { + let env = Env::default(); + + let owner = Address::generate(&env); + let contract_address = env.register(DummyContract, (&owner,)); + let upgrader_address = env.register(Upgrader, ()); + + let original_version: String = query_version(&env, &contract_address); + assert_eq!(original_version, String::from_str(&env, "0.1.0")); + + let hash_after_upgrade = env.deployer().upload_contract_wasm(WASM_AFTER_UPGRADE); + let expected_data = String::from_str(&env, "migration successful"); + let expected_version = String::from_str(&env, "0.2.0"); + + let (upgrade_auth, migrate_auth) = + build_invocation_auths(&env, &contract_address, &hash_after_upgrade, &expected_data); + + // add the owner to the set of authenticated addresses + env.mock_auths(&[ + MockAuth { + address: &owner, + invoke: &upgrade_auth, + }, + MockAuth { + address: &owner, + invoke: &migrate_auth, + }, + ]); + + UpgraderClient::new(&env, &upgrader_address).upgrade( + &contract_address, + &expected_version, + &hash_after_upgrade, + &soroban_sdk::vec![&env, expected_data.to_val()], + ); + + // ensure new version is set correctly + let upgraded_version: String = env.invoke_contract( + &contract_address, + &Symbol::new(&env, VERSION), + soroban_sdk::vec![&env], + ); + assert_eq!(upgraded_version, expected_version); + + // ensure migration was successful + env.as_contract(&contract_address, || { + let data: String = env.storage().instance().get(&DataKey::Data).unwrap(); + assert_eq!(data, expected_data); + }); + } + + #[test] + #[should_panic(expected = "HostError: Error(Auth, InvalidAction)")] + fn upgrade_fails_if_caller_is_authenticated_but_not_owner() { + let env = Env::default(); + + let owner = Address::generate(&env); + let contract_address = env.register(DummyContract, (&owner,)); + let upgrader_address = env.register(Upgrader, ()); + + let hash_after_upgrade = env.deployer().upload_contract_wasm(WASM_AFTER_UPGRADE); + let expected_data = String::from_str(&env, "migration successful"); + let expected_version = String::from_str(&env, "0.2.0"); + + let (upgrade_auth, migrate_auth) = + build_invocation_auths(&env, &contract_address, &hash_after_upgrade, &expected_data); + + // add the caller to the set of authenticated addresses + let caller = Address::generate(&env); + env.mock_auths(&[ + MockAuth { + address: &caller, + invoke: &upgrade_auth, + }, + MockAuth { + address: &caller, + invoke: &migrate_auth, + }, + ]); + + // should panic: caller is authenticated, but not the owner + UpgraderClient::new(&env, &upgrader_address).upgrade( + &contract_address, + &expected_version, + &hash_after_upgrade, + &soroban_sdk::vec![&env, expected_data.to_val()], + ); + } + + #[test] + #[should_panic(expected = "HostError: Error(Auth, InvalidAction)")] + fn upgrade_fails_if_correct_owner_is_not_authenticated_for_full_invocation_tree() { + let env = Env::default(); + + let owner = Address::generate(&env); + let contract_address = env.register(DummyContract, (&owner,)); + + let upgrader_address = env.register(Upgrader, ()); + + let hash_after_upgrade = env.deployer().upload_contract_wasm(WASM_AFTER_UPGRADE); + let expected_data = String::from_str(&env, "migration successful"); + let expected_version = String::from_str(&env, "0.2.0"); + + let (upgrade_auth, migrate_auth) = + build_invocation_auths(&env, &contract_address, &hash_after_upgrade, &expected_data); + + // only add the owner to the set of authenticated addresses for the upgrade function, and the caller for the migrate function + let caller = Address::generate(&env); + env.mock_auths(&[ + MockAuth { + address: &owner, + invoke: &upgrade_auth, + }, + MockAuth { + address: &caller, + invoke: &migrate_auth, + }, + ]); + + UpgraderClient::new(&env, &upgrader_address).upgrade( + &contract_address, + &expected_version, + &hash_after_upgrade, + &soroban_sdk::vec![&env, expected_data.to_val()], + ); + } + + fn build_invocation_auths<'a>( + env: &Env, + contract_address: &'a Address, + hash_after_upgrade: &'a BytesN<32>, + expected_data: &'a String, + ) -> (MockAuthInvoke<'a>, MockAuthInvoke<'a>) { + let upgrade = MockAuthInvoke { + contract: contract_address, + fn_name: UPGRADE, + args: soroban_sdk::vec![&env, hash_after_upgrade.to_val()], + sub_invokes: &[], + }; + let migrate = MockAuthInvoke { + contract: contract_address, + fn_name: MIGRATE, + args: soroban_sdk::vec![&env, expected_data.to_val()], + sub_invokes: &[], + }; + (upgrade, migrate) + } + + fn query_version(env: &Env, contract_address: &Address) -> String { + env.invoke_contract( + contract_address, + &Symbol::new(env, VERSION), + soroban_sdk::vec![&env], + ) + } +} diff --git a/contracts/upgrader/src/error.rs b/contracts/upgrader/src/error.rs new file mode 100644 index 00000000..61cab3b3 --- /dev/null +++ b/contracts/upgrader/src/error.rs @@ -0,0 +1,8 @@ +use soroban_sdk::contracterror; + +#[contracterror] +#[repr(u32)] +pub enum ContractError { + SameVersion = 1, + UnexpectedNewVersion = 2, +} diff --git a/contracts/upgrader/src/lib.rs b/contracts/upgrader/src/lib.rs new file mode 100644 index 00000000..c5aa892e --- /dev/null +++ b/contracts/upgrader/src/lib.rs @@ -0,0 +1,6 @@ +#![no_std] +#[cfg(test)] +extern crate alloc; + +pub mod contract; +pub mod error; diff --git a/contracts/upgrader/src/testdata/dummy.wasm b/contracts/upgrader/src/testdata/dummy.wasm new file mode 100755 index 0000000000000000000000000000000000000000..8a2d1a7fcde97ca462922768888d37b3a61f1c1b GIT binary patch literal 1442 zcmZuxOK%%h6h7z9%gObmQ&j>rLTH?_DN-%x)wsLNl(a%#0EPWzJaf~;iS01sBOWx30{%id=gy3iBCh1~_|E&DxrR9JBLLv1wQVsT<9HjH z7~?{okSrzz9m6(|3LrM-@E9LbP#5@p;i`Szm|!rSz5zLb;AP2QF?a4ec3<^}*&_kYvC8tj;Q;E+(c!}^P8GOLe~+Y* zf-4xowfQJY<53)`L296kqFogqM%_49hL}IKWG;}VxG|*zfw#YepJ-8RicKGaclfOf z!PDs*GFsjXc4~+^%HV~D%nFh|`ojC3?G%SM4fuJ>1pvZt8nuS-G4OgtW?#r(QQ+8| zuxBvWaUrCnJ~j*=8m8DZHhp8u#Q+-?d6>5Vmh9k9xaV?eJNUB4T?O->m-;W00$3z~ z%s-Xt^^R+iy47n~bsfPk7bRV~_mWNCDbq#rutGUu_eQ`2S*=O|0!ZTwb84gBSoQ(2Al^oNn znVs2(Un0~dcrz=&>^Ts|Ha_k^okS<}u%q2L-_?-u4>6y9t zmJPGQP|?{VBcRH^P&_<(j{3=I*QzH`1rm37x{i9p&}H1xqhE3)(bP9V{1W_seN{ck zuZMkgFWx&i$`pq%UfEc;z8UVT0ZSLPoj6T1mFJ9IV?xJ{`@^HbNXrsFzFI9p4UYS2 z6wh|?f%eE}i+ay!WjXynX%DcMo9*T1#R_X#o~QeTd2NOE-fZ25gizuXNLY0neN&0ssI2 literal 0 HcmV?d00001 diff --git a/packages/axelar-soroban-std/src/lib.rs b/packages/axelar-soroban-std/src/lib.rs index 99182dd0..e4677c57 100644 --- a/packages/axelar-soroban-std/src/lib.rs +++ b/packages/axelar-soroban-std/src/lib.rs @@ -6,9 +6,12 @@ pub mod testutils; #[cfg(any(test, feature = "testutils"))] pub use testutils::*; -#[cfg(any(test, feature = "testutils"))] pub mod traits; pub mod types; pub mod error; + +mod upgrade; + +pub use upgrade::UpgradeableInterface; diff --git a/packages/axelar-soroban-std/src/traits.rs b/packages/axelar-soroban-std/src/traits.rs index 34096dfd..ee322b81 100644 --- a/packages/axelar-soroban-std/src/traits.rs +++ b/packages/axelar-soroban-std/src/traits.rs @@ -1,13 +1,29 @@ -extern crate std; +#[cfg(any(test, feature = "testutils"))] +pub use testutils::*; -use soroban_sdk::{Env, IntoVal, TryFromVal, Val, Vec}; +pub trait ThenOk { + fn then_ok(self, ok: T, err: E) -> Result; +} -pub trait IntoVec { - fn into_vec(self, env: &Env) -> Vec; +impl ThenOk for bool { + fn then_ok(self, ok: T, err: E) -> Result { + self.then_some(ok).ok_or(err) + } } -impl + TryFromVal> IntoVec for std::vec::Vec { - fn into_vec(self, env: &Env) -> Vec { - Vec::from_slice(env, self.as_slice()) +#[cfg(any(test, feature = "testutils"))] +mod testutils { + extern crate std; + + use soroban_sdk::{Env, IntoVal, TryFromVal, Val, Vec}; + + pub trait IntoVec { + fn into_vec(self, env: &Env) -> Vec; + } + + impl + TryFromVal> IntoVec for std::vec::Vec { + fn into_vec(self, env: &Env) -> Vec { + Vec::from_slice(env, self.as_slice()) + } } } diff --git a/packages/axelar-soroban-std/src/upgrade.rs b/packages/axelar-soroban-std/src/upgrade.rs new file mode 100644 index 00000000..fbe8b04e --- /dev/null +++ b/packages/axelar-soroban-std/src/upgrade.rs @@ -0,0 +1,11 @@ +use soroban_sdk::{BytesN, Env, String}; + +pub trait UpgradeableInterface { + type Error: Into; + + /// Returns the current version of the contract. + fn version(env: Env) -> String; + + /// Upgrades the contract to a new WASM hash. + fn upgrade(env: Env, new_wasm_hash: BytesN<32>) -> Result<(), Self::Error>; +} From 9c49a73346d161b8bd52060ef764db04464ceb80 Mon Sep 17 00:00:00 2001 From: Attiss Ngo <92927591+AttissNgo@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:04:23 -0600 Subject: [PATCH 2/3] feat(ITS): add ITS message ABI encoding/decoding support (#65) Co-authored-by: Milap Sheth --- Cargo.lock | 1177 ++++++++++++++--- Cargo.toml | 14 +- contracts/interchain-token-service/Cargo.toml | 8 +- contracts/interchain-token-service/src/abi.rs | 559 ++++++++ contracts/interchain-token-service/src/lib.rs | 4 + ...ploy_interchain_token_encode_decode.golden | 8 + .../interchain_transfer_encode_decode.golden | 6 + .../interchain-token-service/src/types.rs | 37 +- 8 files changed, 1580 insertions(+), 233 deletions(-) create mode 100644 contracts/interchain-token-service/src/abi.rs create mode 100644 contracts/interchain-token-service/src/testdata/deploy_interchain_token_encode_decode.golden create mode 100644 contracts/interchain-token-service/src/testdata/interchain_transfer_encode_decode.golden diff --git a/Cargo.lock b/Cargo.lock index 8e88f073..bc75e88b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,6 +14,97 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "alloy-primitives" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccb3ead547f4532bc8af961649942f0b9c16ee9226e26caa3f38420651cc0bf4" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "hex-literal", + "itoa", + "k256", + "keccak-asm", + "proptest", + "rand", + "ruint", + "serde", + "tiny-keccak", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0822426598f95e45dd1ea32a738dac057529a709ee645fcc516ffa4cbde08f" +dependencies = [ + "arrayvec", + "bytes", +] + +[[package]] +name = "alloy-sol-macro" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b40397ddcdcc266f59f959770f601ce1280e699a91fc1862f29cef91707cd09" +dependencies = [ + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "alloy-sol-macro-expander" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "867a5469d61480fea08c7333ffeca52d5b621f5ca2e44f271b117ec1fc9a0525" +dependencies = [ + "alloy-sol-macro-input", + "const-hex", + "heck", + "indexmap 2.6.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.87", + "syn-solidity", + "tiny-keccak", +] + +[[package]] +name = "alloy-sol-macro-input" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e482dc33a32b6fadbc0f599adea520bd3aaa585c141a80b404d0a3e3fa72528" +dependencies = [ + "const-hex", + "dunce", + "heck", + "proc-macro2", + "quote", + "syn 2.0.87", + "syn-solidity", +] + +[[package]] +name = "alloy-sol-types" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a91ca40fa20793ae9c3841b83e74569d1cc9af29a2f5237314fd3452d51e38c7" +dependencies = [ + "alloy-primitives", + "alloy-sol-macro", + "const-hex", + "serde", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -31,9 +122,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.90" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "arbitrary" @@ -51,9 +142,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" dependencies = [ "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", ] [[package]] @@ -62,10 +153,10 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" dependencies = [ - "ark-ff", + "ark-ff 0.4.2", "ark-poly", - "ark-serialize", - "ark-std", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "derivative", "hashbrown 0.13.2", "itertools", @@ -73,26 +164,54 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + [[package]] name = "ark-ff" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" dependencies = [ - "ark-ff-asm", - "ark-ff-macros", - "ark-serialize", - "ark-std", + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "derivative", - "digest", + "digest 0.10.7", "itertools", "num-bigint", "num-traits", "paste", - "rustc_version", + "rustc_version 0.4.1", "zeroize", ] +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "ark-ff-asm" version = "0.4.2" @@ -103,6 +222,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + [[package]] name = "ark-ff-macros" version = "0.4.2" @@ -122,13 +253,23 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" dependencies = [ - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "derivative", "hashbrown 0.13.2", ] +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + [[package]] name = "ark-serialize" version = "0.4.2" @@ -136,8 +277,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" dependencies = [ "ark-serialize-derive", - "ark-std", - "digest", + "ark-std 0.4.0", + "digest 0.10.7", "num-bigint", ] @@ -152,6 +293,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand", +] + [[package]] name = "ark-std" version = "0.4.0" @@ -162,11 +313,28 @@ dependencies = [ "rand", ] +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axelar-gas-service" @@ -220,9 +388,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.7" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" @@ -230,6 +398,39 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -241,9 +442,27 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.3" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "bytes-lit" @@ -254,14 +473,17 @@ dependencies = [ "num-bigint", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.87", ] [[package]] name = "cc" -version = "1.0.89" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -271,9 +493,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.34" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -282,23 +504,42 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "const-hex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0121754e84117e65f9d90648ee6aa4882a6e63110307ab73967a4c5e7e69e586" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", +] + [[package]] name = "const-oid" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] @@ -314,6 +555,12 @@ dependencies = [ "serde_json", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -338,12 +585,12 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" +checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote", - "syn 2.0.39", + "syn 2.0.87", ] [[package]] @@ -355,9 +602,9 @@ dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", - "digest", + "digest 0.10.7", "fiat-crypto", - "rustc_version", + "rustc_version 0.4.1", "subtle", "zeroize", ] @@ -370,14 +617,14 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.87", ] [[package]] name = "darling" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ "darling_core", "darling_macro", @@ -385,27 +632,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.39", + "syn 2.0.87", ] [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.39", + "syn 2.0.87", ] [[package]] @@ -416,9 +663,9 @@ checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "zeroize", @@ -453,7 +700,20 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.87", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.1", + "syn 2.0.87", ] [[package]] @@ -462,6 +722,15 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.7" @@ -476,9 +745,15 @@ dependencies = [ [[package]] name = "downcast-rs" -version = "1.2.0" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dunce" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "ecdsa" @@ -487,10 +762,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", - "digest", + "digest 0.10.7", "elliptic-curve", "rfc6979", "signature", + "spki", ] [[package]] @@ -520,9 +796,9 @@ dependencies = [ [[package]] name = "either" -version = "1.10.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elliptic-curve" @@ -532,10 +808,11 @@ checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", - "digest", + "digest 0.10.7", "ff", "generic-array", "group", + "pkcs8", "rand_core", "sec1", "subtle", @@ -548,6 +825,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "escape-bytes" version = "0.1.1" @@ -570,6 +857,23 @@ dependencies = [ "soroban-sdk", ] +[[package]] +name = "fastrand" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" + +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + [[package]] name = "ff" version = "0.13.0" @@ -582,9 +886,21 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.6" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] [[package]] name = "fnv" @@ -592,6 +908,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "generic-array" version = "0.14.7" @@ -605,9 +927,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "js-sys", @@ -659,9 +981,15 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" + +[[package]] +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hex" @@ -684,14 +1012,14 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -716,6 +1044,26 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -729,12 +1077,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.5" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.15.1", "serde", ] @@ -765,7 +1113,11 @@ dependencies = [ name = "interchain-token-service" version = "0.1.0" dependencies = [ + "alloy-primitives", + "alloy-sol-types", "axelar-soroban-std", + "goldie", + "hex", "soroban-sdk", ] @@ -780,15 +1132,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -802,6 +1154,7 @@ dependencies = [ "cfg-if", "ecdsa", "elliptic-curve", + "once_cell", "sha2", ] @@ -814,31 +1167,58 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "keccak-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" -version = "0.2.153" +version = "0.2.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", ] @@ -851,39 +1231,39 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-derive" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.87", ] [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "p256" @@ -897,11 +1277,48 @@ dependencies = [ "sha2", ] +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pest" +version = "2.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] [[package]] name = "pkcs8" @@ -921,9 +1338,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "pretty_assertions" @@ -937,12 +1357,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.15" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.39", + "syn 2.0.87", ] [[package]] @@ -954,24 +1374,100 @@ dependencies = [ "elliptic-curve", ] +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] +[[package]] +name = "proptest" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quote" -version = "1.0.33" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.8.5" @@ -1002,6 +1498,21 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + [[package]] name = "rfc6979" version = "0.4.0" @@ -1012,82 +1523,182 @@ dependencies = [ "subtle", ] +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + +[[package]] +name = "ruint" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp", + "num-bigint", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver", + "semver 1.0.23", +] + +[[package]] +name = "rustix" +version = "0.38.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", ] [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "sec1" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", "generic-array", + "pkcs8", "subtle", "zeroize", ] [[package]] name = "semver" -version = "1.0.22" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] [[package]] name = "serde" -version = "1.0.192" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.87", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_with" -version = "3.6.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.5", + "indexmap 2.6.0", "serde", "serde_derive", "serde_json", @@ -1097,14 +1708,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.6.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "865f9743393e638991566a8b7a479043c2c8da94a33e0a31f18214c9cae0a64d" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.87", ] [[package]] @@ -1115,7 +1726,7 @@ checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.7", ] [[package]] @@ -1124,25 +1735,41 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest", + "digest 0.10.7", "keccak", ] +[[package]] +name = "sha3-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +dependencies = [ + "cc", + "cfg-if", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signature" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest", + "digest 0.10.7", "rand_core", ] [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "soroban-builtin-sdk-macros" @@ -1153,7 +1780,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.87", ] [[package]] @@ -1193,8 +1820,8 @@ checksum = "8cb9be0260d39a648db0d33e1c6f8f494ec0c4f5be2b8a0a4e15ed4b7c6a92b0" dependencies = [ "ark-bls12-381", "ark-ec", - "ark-ff", - "ark-serialize", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", "curve25519-dalek", "ecdsa", "ed25519-dalek", @@ -1233,14 +1860,14 @@ dependencies = [ "serde", "serde_json", "stellar-xdr", - "syn 2.0.39", + "syn 2.0.87", ] [[package]] name = "soroban-ledger-snapshot" -version = "22.0.0-rc.3" +version = "22.0.0-rc.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56375490f176006a636db0e50c2269c55626e0ff7222711bb78d77028376fe0d" +checksum = "23a4ca0a3cede93a08a2eedb7547fb6095c007975c8c7139f7126350371afe1f" dependencies = [ "serde", "serde_json", @@ -1252,16 +1879,17 @@ dependencies = [ [[package]] name = "soroban-sdk" -version = "22.0.0-rc.3" +version = "22.0.0-rc.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d063d0df000aaec20105aab3d743660322bc0269934ea95d79fa19aa8792385" +checksum = "0750607b238ba62447cb6038daf834f173861b5db43577ae68d351127dd5439c" dependencies = [ "arbitrary", "bytes-lit", "ctor", + "derive_arbitrary", "ed25519-dalek", "rand", - "rustc_version", + "rustc_version 0.4.1", "serde", "serde_json", "soroban-env-guest", @@ -1273,29 +1901,29 @@ dependencies = [ [[package]] name = "soroban-sdk-macros" -version = "22.0.0-rc.3" +version = "22.0.0-rc.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "508c9d819a05109120664aab86c371e1b72c5bea20b1a13158b4ef7948d9f673" +checksum = "d5edc95c3923c3d61da4fbc6ac606ac97e1fabf9c4d2ab7849757e8e875bd239" dependencies = [ "crate-git-revision", "darling", "itertools", "proc-macro2", "quote", - "rustc_version", + "rustc_version 0.4.1", "sha2", "soroban-env-common", "soroban-spec", "soroban-spec-rust", "stellar-xdr", - "syn 2.0.39", + "syn 2.0.87", ] [[package]] name = "soroban-spec" -version = "22.0.0-rc.3" +version = "22.0.0-rc.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69001c97783ed3ce197eac2404e7beeabedd16e40e6f0aa210d1bc6a13063c33" +checksum = "4afa4d83de8965586f735e9d4724fd44f0d119980718064f7658f3fe50c01782" dependencies = [ "base64 0.13.1", "stellar-xdr", @@ -1305,9 +1933,9 @@ dependencies = [ [[package]] name = "soroban-spec-rust" -version = "22.0.0-rc.3" +version = "22.0.0-rc.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45dbf346f91ed23ea63b1c256c522da9e6f0e2db1887b990a8f0f1d842a3093" +checksum = "431b6ab7b2ae63c24ed88e828c9ef7b5541c314df34336a9e5837c6e0d6c7ae0" dependencies = [ "prettyplease", "proc-macro2", @@ -1315,7 +1943,7 @@ dependencies = [ "sha2", "soroban-spec", "stellar-xdr", - "syn 2.0.39", + "syn 2.0.87", "thiserror", ] @@ -1383,15 +2011,15 @@ dependencies = [ [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -1406,40 +2034,71 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "syn-solidity" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c837dc8852cb7074e46b444afb81783140dab12c58867b49fb3898fbafedf7ea" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "thiserror" -version = "1.0.55" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e3de26b0965292219b4287ff031fcba86837900fe9cd2b34ea8ad893c0953d2" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.55" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "268026685b2be38d7103e9e507c938a1fcb3d7e6eb15e87870b617bf37b6d581" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.87", ] [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -1458,25 +2117,75 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap 2.6.0", + "toml_datetime", + "winnow", +] + [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-width" @@ -1503,11 +2212,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] [[package]] name = "wasi" @@ -1517,34 +2241,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.87", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1552,22 +2277,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wasmi_arena" @@ -1593,15 +2318,15 @@ version = "0.116.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a58e28b80dd8340cb07b8242ae654756161f6fc8d0038123d679b7b99964fa50" dependencies = [ - "indexmap 2.2.5", - "semver", + "indexmap 2.6.0", + "semver 1.0.23", ] [[package]] name = "wasmparser-nostd" -version = "0.100.1" +version = "0.100.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9157cab83003221bfd385833ab587a039f5d6fa7304854042ba358a3b09e0724" +checksum = "d5a015fe95f3504a94bb1462c717aae75253e39b9dd6c3fb1062c934535c64aa" dependencies = [ "indexmap-nostd", ] @@ -1615,15 +2340,34 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -1632,45 +2376,69 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] [[package]] name = "yansi" @@ -1684,6 +2452,7 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] @@ -1695,14 +2464,14 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.87", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -1715,5 +2484,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.87", ] diff --git a/Cargo.toml b/Cargo.toml index 315feb5e..9d1893fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,6 @@ [workspace] resolver = "2" -members = [ - "contracts/*", - "integration-tests", - "packages/*", -] +members = ["contracts/*", "integration-tests", "packages/*"] [workspace.package] edition = "2021" @@ -18,8 +14,12 @@ axelar-gas-service = { version = "^0.1.0", path = "contracts/axelar-gas-service" axelar-gateway = { version = "^0.1.0", path = "contracts/axelar-gateway" } axelar-operators = { version = "^0.1.0", path = "contracts/axelar-operators" } interchain-token-service = { version = "^0.1.0", path = "contracts/interchain-token-service" } -interchain-token = { version = "^0.1.0", path = "contracts/interchain-token" } -example = { version = "^0.1.0", path = "contracts/example" } +alloy-primitives = { version = "0.7.6", default-features = false, features = [ + "std", +] } +alloy-sol-types = { version = "0.7.6", default-features = false, features = [ + "std", +] } [workspace.lints.clippy] nursery = "warn" diff --git a/contracts/interchain-token-service/Cargo.toml b/contracts/interchain-token-service/Cargo.toml index 435d170a..2ba4ec2b 100644 --- a/contracts/interchain-token-service/Cargo.toml +++ b/contracts/interchain-token-service/Cargo.toml @@ -10,12 +10,16 @@ publish = true crate-type = ["cdylib", "rlib"] [dependencies] +alloy-primitives = { workspace = true } +alloy-sol-types = { workspace = true } axelar-soroban-std = { workspace = true } -soroban-sdk = { workspace = true } +soroban-sdk = { workspace = true, features = ["alloc"] } [dev-dependencies] axelar-soroban-std = { workspace = true, features = ["testutils"] } -soroban-sdk = { workspace = true, features = ["testutils"] } +goldie = { version = "0.5" } +hex = "0.4" +soroban-sdk = { workspace = true, features = ["testutils", "alloc"] } [features] testutils = ["soroban-sdk/testutils", "axelar-soroban-std/testutils"] diff --git a/contracts/interchain-token-service/src/abi.rs b/contracts/interchain-token-service/src/abi.rs new file mode 100644 index 00000000..d69bb3c1 --- /dev/null +++ b/contracts/interchain-token-service/src/abi.rs @@ -0,0 +1,559 @@ +use alloy_primitives::{FixedBytes, Uint, U256}; +use alloy_sol_types::{sol, SolValue}; +use axelar_soroban_std::ensure; +use soroban_sdk::{contracterror, Bytes, BytesN, Env, String}; + +use crate::types::{self, HubMessage, Message}; +extern crate alloc; +use crate::abi::alloc::{string::String as StdString, vec}; + +#[contracterror] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[repr(u32)] +pub enum MessageError { + InsufficientMessageLength = 0, + InvalidMessageType = 1, + AbiDecodeFailed = 2, + InvalidAmount = 3, + InvalidUtf8 = 4, +} + +sol! { + enum MessageType { + InterchainTransfer, + DeployInterchainToken, + DeployTokenManager, // note, this case is not supported by the ITS hub + SendToHub, + ReceiveFromHub + } + + struct InterchainTransfer { + uint256 messageType; + bytes32 tokenId; + bytes sourceAddress; + bytes destinationAddress; + uint256 amount; + bytes data; + } + + struct DeployInterchainToken { + uint256 messageType; + bytes32 tokenId; + string name; + string symbol; + uint8 decimals; + bytes minter; + } + + struct SendToHub { + uint256 messageType; + string destination_chain; + bytes message; + } + + struct ReceiveFromHub { + uint256 messageType; + string source_chain; + bytes message; + } +} + +impl Message { + pub fn abi_encode(self, env: &Env) -> Result { + let msg = match self { + Self::InterchainTransfer(types::InterchainTransfer { + token_id, + source_address, + destination_address, + amount, + data, + }) => InterchainTransfer { + messageType: MessageType::InterchainTransfer.into(), + tokenId: FixedBytes::<32>::new(token_id.into()), + sourceAddress: source_address.to_alloc_vec().into(), + destinationAddress: destination_address.to_alloc_vec().into(), + amount: amount.try_into().expect("failed to convert"), + data: into_vec(data).into(), + } + .abi_encode_params(), + Self::DeployInterchainToken(types::DeployInterchainToken { + token_id, + name, + symbol, + decimals, + minter, + }) => DeployInterchainToken { + messageType: MessageType::DeployInterchainToken.into(), + tokenId: FixedBytes::<32>::new(token_id.into()), + name: to_std_string(name)?, + symbol: to_std_string(symbol)?, + decimals, + minter: into_vec(minter).into(), + } + .abi_encode_params(), + }; + Ok(Bytes::from_slice(env, &msg)) + } + + pub fn abi_decode(env: &Env, payload: &Bytes) -> Result { + ensure!(payload.len() >= 32, MessageError::InsufficientMessageLength); + + let payload = payload.to_alloc_vec(); + + let message_type = MessageType::abi_decode(&payload[0..32], true) + .map_err(|_| MessageError::InvalidMessageType)?; + + match message_type { + MessageType::InterchainTransfer => { + let decoded = InterchainTransfer::abi_decode_params(&payload, true) + .map_err(|_| MessageError::AbiDecodeFailed)?; + + Ok(Self::InterchainTransfer(types::InterchainTransfer { + token_id: BytesN::from_array(env, &decoded.tokenId.into()), + source_address: Bytes::from_slice(env, decoded.sourceAddress.as_ref()), + destination_address: Bytes::from_slice( + env, + decoded.destinationAddress.as_ref(), + ), + amount: to_i128(decoded.amount)?, + data: from_vec(env, decoded.data.as_ref()), + })) + } + MessageType::DeployInterchainToken => { + let decoded = DeployInterchainToken::abi_decode_params(&payload, true) + .map_err(|_| MessageError::AbiDecodeFailed)?; + + Ok(Self::DeployInterchainToken(types::DeployInterchainToken { + token_id: BytesN::from_array(env, &decoded.tokenId.into()), + name: String::from_str(env, &decoded.name), + symbol: String::from_str(env, &decoded.symbol), + decimals: decoded.decimals, + minter: from_vec(env, decoded.minter.as_ref()), + })) + } + _ => Err(MessageError::InvalidMessageType), + } + } +} + +#[allow(dead_code)] +impl HubMessage { + pub fn abi_encode(self, env: &Env) -> Result { + let msg = match self { + Self::SendToHub { + destination_chain, + message, + } => SendToHub { + messageType: MessageType::SendToHub.into(), + destination_chain: to_std_string(destination_chain)?, + message: message.abi_encode(env)?.to_alloc_vec().into(), + } + .abi_encode_params(), + Self::ReceiveFromHub { + source_chain, + message, + } => ReceiveFromHub { + messageType: MessageType::ReceiveFromHub.into(), + source_chain: to_std_string(source_chain)?, + message: message.abi_encode(env)?.to_alloc_vec().into(), + } + .abi_encode_params(), + }; + Ok(Bytes::from_slice(env, &msg)) + } + + pub fn abi_decode(env: &Env, payload: &Bytes) -> Result { + ensure!(payload.len() >= 32, MessageError::InsufficientMessageLength); + + let payload = payload.to_alloc_vec(); + + let message_type = MessageType::abi_decode(&payload[0..32], true) + .map_err(|_| MessageError::InvalidMessageType)?; + + match message_type { + MessageType::SendToHub => { + let decoded = SendToHub::abi_decode_params(&payload, true) + .map_err(|_| MessageError::AbiDecodeFailed)?; + + Ok(Self::SendToHub { + destination_chain: String::from_str(env, &decoded.destination_chain), + message: Message::abi_decode( + env, + &Bytes::from_slice(env, decoded.message.as_ref()), + )?, + }) + } + MessageType::ReceiveFromHub => { + let decoded = ReceiveFromHub::abi_decode_params(&payload, true) + .map_err(|_| MessageError::AbiDecodeFailed)?; + + Ok(Self::ReceiveFromHub { + source_chain: String::from_str(env, &decoded.source_chain), + message: Message::abi_decode( + env, + &Bytes::from_slice(env, decoded.message.as_ref()), + )?, + }) + } + _ => Err(MessageError::InvalidMessageType), + } + } +} + +fn to_std_string(soroban_string: String) -> Result { + let length = soroban_string.len() as usize; + let mut bytes = vec![0u8; length]; + soroban_string.copy_into_slice(&mut bytes); + StdString::from_utf8(bytes).map_err(|_| MessageError::InvalidUtf8) +} + +fn to_i128(value: Uint<256, 4>) -> Result { + let slice = value.as_le_slice(); + + let mut bytes_to_remove = [0; 16]; + let mut bytes_to_convert = [0; 16]; + bytes_to_convert.copy_from_slice(&slice[..16]); + bytes_to_remove.copy_from_slice(&slice[16..]); + + ensure!( + i128::from_le_bytes(bytes_to_remove) == 0, + MessageError::InvalidAmount + ); + + let i128_value = i128::from_le_bytes(bytes_to_convert); + + ensure!(i128_value >= 0, MessageError::InvalidAmount); + + Ok(i128_value) +} + +fn into_vec(value: Option) -> alloc::vec::Vec { + value.map(|d| d.to_alloc_vec()).unwrap_or_default() +} + +fn from_vec(env: &Env, value: &[u8]) -> Option { + if value.is_empty() { + None + } else { + Some(Bytes::from_slice(env, value)) + } +} + +impl From for U256 { + fn from(value: MessageType) -> Self { + Self::from(value as u8) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use alloc::vec; + use axelar_soroban_std::assert_ok; + use core::u128; + use soroban_sdk::{Bytes, BytesN, Env, String}; + use std::vec::Vec; + + fn bytes_from_hex(env: &Env, hex_string: &str) -> Bytes { + let bytes_vec: Vec = hex::decode(hex_string).unwrap(); + Bytes::from_slice(env, &bytes_vec) + } + + #[test] + fn soroban_str_to_std_string() { + let env = Env::default(); + + let plain_string = "hello world"; + let plain_string_soroban = String::from_str(&env, &plain_string); + assert_eq!( + to_std_string(plain_string_soroban).unwrap(), + StdString::from(plain_string) + ); + + let var_length_chars = "πŸŽ‰δΈ­πŸš€Ο€πŸŒˆβ‚¬"; + let var_length_chars_soroban = String::from_str(&env, &var_length_chars); + assert_eq!( + to_std_string(var_length_chars_soroban).unwrap(), + StdString::from(var_length_chars) + ); + + let null_bytes = "Hello\x00World"; + let null_bytes_soroban = String::from_str(&env, &null_bytes); + assert_eq!( + to_std_string(null_bytes_soroban).unwrap(), + StdString::from(null_bytes) + ); + + let escape_char = "Hello\tWorld"; + let escape_char_soroban = String::from_str(&env, &escape_char); + assert_eq!( + to_std_string(escape_char_soroban).unwrap(), + StdString::from(escape_char) + ); + } + + #[test] + fn to_std_string_fails_invalid_utf8_bytes() { + let env = Env::default(); + + let invalid_sequences = vec![ + String::from_bytes(&env, &vec![0xF5, 0x90, 0x80]), // not valid utf-8 + String::from_bytes(&env, &vec![0x00, 0x01, 0x02, 0xC0]), // valid ASCII characters followed by an invalid UTF-8 starting byte + String::from_bytes(&env, &vec![0xC0, 0x80, 0xF5, 0x90]), // invalid UTF-8 starting byte followed by valid UTF-8 sequences + String::from_bytes(&env, &vec![0xF0, 0x90, 0x80, 0xDF, 0xFB, 0xBF]), // surrogate pairs with invalid charaters "\uD800\uDDFF" + String::from_bytes(&env, &vec![0xF4, 0x90, 0x80, 0x80]), // outside the Basic Multilingual Plane + ]; + + for sequence in invalid_sequences { + let result = to_std_string(sequence); + assert!(matches!(result, Err(MessageError::InvalidUtf8))); + } + } + + #[test] + fn uint256_to_i128() { + let uint_i128_max: Uint<256, 4> = i128::MAX.try_into().unwrap(); + + assert_eq!(to_i128(uint_i128_max).unwrap(), i128::MAX); + + let uint_min: Uint<256, 4> = Uint::MIN; + + assert_eq!(to_i128(uint_min).unwrap(), 0); + } + + #[test] + fn to_i128_fails_dirty_bytes() { + let uint_min: Uint<256, 4> = Uint::from(1); + let bytes: [u8; 32] = uint_min.to_le_bytes(); + assert_eq!( + [ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 + ], + bytes + ); + + let bad_bytes = [ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, + ]; + let bad_uint = U256::from_le_bytes(bad_bytes); + + let result = to_i128(bad_uint); + + assert!(matches!(result, Err(MessageError::InvalidAmount))); + } + + #[test] + fn to_i128_fails_overflow() { + let overflow: Uint<256, 4> = Uint::from(i128::MAX) + Uint::from(1); + let result = to_i128(overflow); + assert!(matches!(result, Err(MessageError::InvalidAmount))); + + let overflow: Uint<256, 4> = Uint::from(u128::MAX); + let result = to_i128(overflow); + assert!(matches!(result, Err(MessageError::InvalidAmount))); + } + + #[test] + fn interchain_transfer_encode_decode() { + let env = Env::default(); + let remote_chain = String::from_str(&env, &"chain"); + + let cases = vec![ + types::HubMessage::SendToHub { + destination_chain: remote_chain.clone(), + message: types::Message::InterchainTransfer(types::InterchainTransfer { + token_id: BytesN::from_array(&env, &[0u8; 32]), + source_address: bytes_from_hex(&env, "00"), + destination_address: bytes_from_hex(&env, "00"), + amount: 1u64.try_into().unwrap(), + data: None, + }) + .into(), + }, + types::HubMessage::SendToHub { + destination_chain: remote_chain.clone(), + message: types::Message::InterchainTransfer(types::InterchainTransfer { + token_id: BytesN::from_array(&env, &[255u8; 32]), + source_address: bytes_from_hex( + &env, + "4F4495243837681061C4743b74B3eEdf548D56A5", + ), + destination_address: bytes_from_hex( + &env, + "4F4495243837681061C4743b74B3eEdf548D56A5", + ), + amount: i128::MAX, + data: Some(bytes_from_hex(&env, "abcd")), + }) + .into(), + }, + types::HubMessage::ReceiveFromHub { + source_chain: remote_chain.clone(), + message: types::Message::InterchainTransfer(types::InterchainTransfer { + token_id: BytesN::from_array(&env, &[0u8; 32]), + source_address: bytes_from_hex(&env, "00"), + destination_address: bytes_from_hex(&env, "00"), + amount: 1u64.try_into().unwrap(), + data: None, + }) + .into(), + }, + types::HubMessage::ReceiveFromHub { + source_chain: remote_chain.clone(), + message: types::Message::InterchainTransfer(types::InterchainTransfer { + token_id: BytesN::from_array(&env, &[255u8; 32]), + source_address: bytes_from_hex( + &env, + "4F4495243837681061C4743b74B3eEdf548D56A5", + ), + destination_address: bytes_from_hex( + &env, + "4F4495243837681061C4743b74B3eEdf548D56A5", + ), + amount: i128::MAX, + data: Some(bytes_from_hex(&env, "abcd")), + }) + .into(), + }, + ]; + + let encoded: Vec<_> = cases + .iter() + .map(|original| { + hex::encode( + assert_ok!(original.clone().abi_encode(&env)) + .to_buffer::<1024>() + .as_slice(), + ) + }) + .collect(); + + goldie::assert_json!(encoded); + + for original in cases { + let encoded = assert_ok!(original.clone().abi_encode(&env)); + let decoded = HubMessage::abi_decode(&env, &encoded); + assert_eq!(original, decoded.unwrap()); + } + } + + #[test] + fn deploy_interchain_token_encode_decode() { + let env = Env::default(); + let remote_chain = String::from_str(&env, &"chain"); + + let cases = vec![ + types::HubMessage::SendToHub { + destination_chain: remote_chain.clone(), + message: types::Message::DeployInterchainToken(types::DeployInterchainToken { + token_id: BytesN::from_array(&env, &[0u8; 32]), + name: String::from_str(&env, &"t"), + symbol: String::from_str(&env, &"T"), + decimals: 0, + minter: None, + }) + .into(), + }, + types::HubMessage::SendToHub { + destination_chain: remote_chain.clone(), + message: types::Message::DeployInterchainToken(types::DeployInterchainToken { + token_id: BytesN::from_array(&env, &[1u8; 32]), + name: String::from_str(&env, &"Test Token"), + symbol: String::from_str(&env, &"TST"), + decimals: 18, + minter: Some(bytes_from_hex(&env, "1234")), + }) + .into(), + }, + types::HubMessage::SendToHub { + destination_chain: remote_chain.clone(), + message: types::Message::DeployInterchainToken(types::DeployInterchainToken { + token_id: BytesN::from_array(&env, &[0u8; 32]), + name: String::from_str(&env, &"Unicode Token πŸͺ™"), + symbol: String::from_str(&env, &"UNIπŸ”£"), + decimals: 255, + minter: Some(bytes_from_hex(&env, "abcd")), + }) + .into(), + }, + types::HubMessage::ReceiveFromHub { + source_chain: remote_chain.clone(), + message: types::Message::DeployInterchainToken(types::DeployInterchainToken { + token_id: BytesN::from_array(&env, &[0u8; 32]), + name: String::from_str(&env, &"t"), + symbol: String::from_str(&env, &"T"), + decimals: 0, + minter: None, + }) + .into(), + }, + types::HubMessage::ReceiveFromHub { + source_chain: remote_chain.clone(), + message: types::Message::DeployInterchainToken(types::DeployInterchainToken { + token_id: BytesN::from_array(&env, &[1u8; 32]), + name: String::from_str(&env, &"Test Token"), + symbol: String::from_str(&env, &"TST"), + decimals: 18, + minter: Some(bytes_from_hex(&env, "1234")), + }) + .into(), + }, + types::HubMessage::ReceiveFromHub { + source_chain: remote_chain.clone(), + message: types::Message::DeployInterchainToken(types::DeployInterchainToken { + token_id: BytesN::from_array(&env, &[0u8; 32]), + name: String::from_str(&env, &"Unicode Token πŸͺ™"), + symbol: String::from_str(&env, &"UNIπŸ”£"), + decimals: 255, + minter: Some(bytes_from_hex(&env, "abcd")), + }) + .into(), + }, + ]; + + let encoded: Vec<_> = cases + .iter() + .map(|original| { + hex::encode( + assert_ok!(original.clone().abi_encode(&env)) + .to_buffer::<1024>() + .as_slice(), + ) + }) + .collect(); + + goldie::assert_json!(encoded); + + for original in cases { + let encoded = assert_ok!(original.clone().abi_encode(&env)); + let decoded = HubMessage::abi_decode(&env, &encoded); + assert_eq!(original, decoded.unwrap()); + } + } + + #[test] + fn abi_decode_fails_invalid_message_type() { + let env = Env::default(); + let bytes = [0u8; 32]; + let invalid_payload = Bytes::from_slice(&env, &bytes); + + let result = HubMessage::abi_decode(&env, &invalid_payload); + assert!(matches!(result, Err(MessageError::InvalidMessageType))); + + let invalid_hub_message_type = assert_ok!(types::Message::InterchainTransfer( + types::InterchainTransfer { + token_id: BytesN::from_array(&env, &[0u8; 32]), + source_address: bytes_from_hex(&env, "00"), + destination_address: bytes_from_hex(&env, "00"), + amount: 1u64.try_into().unwrap(), + data: None, + } + ) + .abi_encode(&env)); + + let result = HubMessage::abi_decode(&env, &invalid_hub_message_type); + assert!(matches!(result, Err(MessageError::InvalidMessageType))); + } +} diff --git a/contracts/interchain-token-service/src/lib.rs b/contracts/interchain-token-service/src/lib.rs index dd6f80a4..5c95e9b3 100644 --- a/contracts/interchain-token-service/src/lib.rs +++ b/contracts/interchain-token-service/src/lib.rs @@ -1,5 +1,6 @@ #![no_std] +mod abi; pub mod error; mod event; mod storage_types; @@ -7,4 +8,7 @@ mod types; pub mod contract; +#[cfg(test)] +extern crate std; + pub use contract::InterchainTokenServiceClient; diff --git a/contracts/interchain-token-service/src/testdata/deploy_interchain_token_encode_decode.golden b/contracts/interchain-token-service/src/testdata/deploy_interchain_token_encode_decode.golden new file mode 100644 index 00000000..76198c15 --- /dev/null +++ b/contracts/interchain-token-service/src/testdata/deploy_interchain_token_encode_decode.golden @@ -0,0 +1,8 @@ +[ + "0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000005636861696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000154000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000005636861696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000001010101010101010101010101010101010101010101010101010101010101010100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000a5465737420546f6b656e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003545354000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021234000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000005636861696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000012556e69636f646520546f6b656e20f09faa9900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007554e49f09f94a3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002abcd000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000005636861696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000154000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000005636861696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000001010101010101010101010101010101010101010101010101010101010101010100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000a5465737420546f6b656e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003545354000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021234000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000005636861696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000012556e69636f646520546f6b656e20f09faa9900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007554e49f09f94a3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002abcd000000000000000000000000000000000000000000000000000000000000" +] \ No newline at end of file diff --git a/contracts/interchain-token-service/src/testdata/interchain_transfer_encode_decode.golden b/contracts/interchain-token-service/src/testdata/interchain_transfer_encode_decode.golden new file mode 100644 index 00000000..5095b4b3 --- /dev/null +++ b/contracts/interchain-token-service/src/testdata/interchain_transfer_encode_decode.golden @@ -0,0 +1,6 @@ +[ + "0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000005636861696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000005636861696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000007fffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000144f4495243837681061c4743b74b3eedf548d56a500000000000000000000000000000000000000000000000000000000000000000000000000000000000000144f4495243837681061c4743b74b3eedf548d56a50000000000000000000000000000000000000000000000000000000000000000000000000000000000000002abcd000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000005636861696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000005636861696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000007fffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000144f4495243837681061c4743b74b3eedf548d56a500000000000000000000000000000000000000000000000000000000000000000000000000000000000000144f4495243837681061c4743b74b3eedf548d56a50000000000000000000000000000000000000000000000000000000000000000000000000000000000000002abcd000000000000000000000000000000000000000000000000000000000000" +] diff --git a/contracts/interchain-token-service/src/types.rs b/contracts/interchain-token-service/src/types.rs index 4922b758..13c5c2d2 100644 --- a/contracts/interchain-token-service/src/types.rs +++ b/contracts/interchain-token-service/src/types.rs @@ -6,46 +6,43 @@ use soroban_sdk::{contracttype, Bytes, BytesN, String}; pub enum MessageType { InterchainTransfer = 0, DeployInterchainToken = 1, - DeployTokenManager = 2, + DeployTokenManager = 2, // note, this case is not supported by the ITS hub SendToHub = 3, ReceiveFromHub = 4, } -#[contracttype] -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[repr(u32)] -pub enum TokenManagerType { - NativeInterchainToken = 0, - MintBurnFrom = 1, - LockUnlock = 2, - LockUnlockFee = 3, - MintBurn = 4, +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Message { + InterchainTransfer(InterchainTransfer), + DeployInterchainToken(DeployInterchainToken), } -#[contracttype] #[derive(Clone, Debug, PartialEq, Eq)] pub struct InterchainTransfer { pub token_id: BytesN<32>, pub source_address: Bytes, pub destination_address: Bytes, - pub amount: u128, - pub data: Bytes, + pub amount: i128, + pub data: Option, } -#[contracttype] #[derive(Clone, Debug, PartialEq, Eq)] pub struct DeployInterchainToken { pub token_id: BytesN<32>, pub name: String, pub symbol: String, - pub decimals: u32, + pub decimals: u8, pub minter: Option, } -#[contracttype] #[derive(Clone, Debug, PartialEq, Eq)] -pub struct DeployTokenManager { - pub token_id: BytesN<32>, - pub token_manager_type: TokenManagerType, - pub params: Bytes, +pub enum HubMessage { + SendToHub { + destination_chain: String, + message: Message, + }, + ReceiveFromHub { + source_chain: String, + message: Message, + }, } From 3bfc6917081f277c4cfcbd3cd8ba25f161f3ed89 Mon Sep 17 00:00:00 2001 From: Milap Sheth Date: Thu, 21 Nov 2024 16:19:38 -0500 Subject: [PATCH 3/3] refactor(axelar-gateway)!: separate gateway messaging interface (#82) --- contracts/axelar-gateway/src/contract.rs | 7 ++- contracts/axelar-gateway/src/error.rs | 4 +- contracts/axelar-gateway/src/executable.rs | 24 ++++++--- contracts/axelar-gateway/src/interface.rs | 50 ++----------------- contracts/axelar-gateway/src/lib.rs | 4 +- .../axelar-gateway/src/messaging_interface.rs | 49 ++++++++++++++++++ contracts/example/src/contract.rs | 6 +-- integration-tests/tests/gmp.rs | 2 +- 8 files changed, 81 insertions(+), 65 deletions(-) create mode 100644 contracts/axelar-gateway/src/messaging_interface.rs diff --git a/contracts/axelar-gateway/src/contract.rs b/contracts/axelar-gateway/src/contract.rs index 96ed5063..300628d8 100644 --- a/contracts/axelar-gateway/src/contract.rs +++ b/contracts/axelar-gateway/src/contract.rs @@ -1,5 +1,6 @@ use crate::error::ContractError; use crate::interface::AxelarGatewayInterface; +use crate::messaging_interface::AxelarGatewayMessagingInterface; use crate::storage_types::{DataKey, MessageApprovalKey, MessageApprovalValue}; use crate::types::{CommandType, Message, Proof, WeightedSigners}; use crate::{auth, event}; @@ -80,7 +81,7 @@ impl AxelarGateway { } #[contractimpl] -impl AxelarGatewayInterface for AxelarGateway { +impl AxelarGatewayMessagingInterface for AxelarGateway { fn call_contract( env: Env, caller: Address, @@ -168,7 +169,9 @@ impl AxelarGatewayInterface for AxelarGateway { false } - +} +#[contractimpl] +impl AxelarGatewayInterface for AxelarGateway { fn approve_messages( env: Env, messages: Vec, diff --git a/contracts/axelar-gateway/src/error.rs b/contracts/axelar-gateway/src/error.rs index e863bb1c..0f91c372 100644 --- a/contracts/axelar-gateway/src/error.rs +++ b/contracts/axelar-gateway/src/error.rs @@ -18,7 +18,5 @@ pub enum ContractError { InvalidEpoch = 11, // Messages EmptyMessages = 12, - // Executable - NotApproved = 13, - MigrationNotAllowed = 14, + MigrationNotAllowed = 13, } diff --git a/contracts/axelar-gateway/src/executable.rs b/contracts/axelar-gateway/src/executable.rs index d32ff378..e55659bc 100644 --- a/contracts/axelar-gateway/src/executable.rs +++ b/contracts/axelar-gateway/src/executable.rs @@ -1,7 +1,15 @@ use axelar_soroban_std::ensure; use soroban_sdk::{contractclient, Address, Bytes, Env, String}; -use crate::{error::ContractError, AxelarGatewayClient}; +use crate::AxelarGatewayMessagingClient; +use soroban_sdk::contracterror; + +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[repr(u32)] +pub enum ExecutableError { + NotApproved = 1, +} /// Interface for an Axelar Executable app. #[contractclient(name = "AxelarExecutableClient")] @@ -9,7 +17,7 @@ pub trait AxelarExecutableInterface { /// Return the trusted gateway contract id. fn gateway(env: &Env) -> Address; - /// Execute a cross-chain contract call with the given payload. This function must validate that the contract call is received from the trusted gateway. + /// Execute a cross-chain message with the given payload. This function must validate that the message is received from the trusted gateway. fn execute( env: Env, source_chain: String, @@ -18,19 +26,19 @@ pub trait AxelarExecutableInterface { payload: Bytes, ); - /// Validate if a gateway has approved a contract call. + /// Validate if a gateway has approved a message. /// This should be called from an implementation of `execute` before executing custom app logic. /// This method doesn't get exposed from the contract, as Soroban SDK's contractimpl macro ignores default trait methods. - fn validate( + fn validate_message( env: &Env, source_chain: &String, message_id: &String, source_address: &String, payload: &Bytes, - ) -> Result<(), ContractError> { - let gateway = AxelarGatewayClient::new(env, &Self::gateway(env)); + ) -> Result<(), ExecutableError> { + let gateway = AxelarGatewayMessagingClient::new(env, &Self::gateway(env)); - // Validate the contract call was approved by the gateway + // Validate that the message was approved by the gateway ensure!( gateway.validate_message( &env.current_contract_address(), @@ -39,7 +47,7 @@ pub trait AxelarExecutableInterface { source_address, &env.crypto().keccak256(payload).into(), ), - ContractError::NotApproved + ExecutableError::NotApproved ); Ok(()) diff --git a/contracts/axelar-gateway/src/interface.rs b/contracts/axelar-gateway/src/interface.rs index 04487326..c30f5fa4 100644 --- a/contracts/axelar-gateway/src/interface.rs +++ b/contracts/axelar-gateway/src/interface.rs @@ -1,57 +1,13 @@ use crate::{ error::ContractError, types::{Message, Proof, WeightedSigners}, + AxelarGatewayMessagingInterface, }; use axelar_soroban_std::UpgradeableInterface; -use soroban_sdk::{contractclient, Address, Bytes, BytesN, Env, String, Vec}; +use soroban_sdk::{contractclient, Address, BytesN, Env, Vec}; #[contractclient(name = "AxelarGatewayClient")] -pub trait AxelarGatewayInterface: UpgradeableInterface { - /// Sends a message to the specified destination chain and contarct address with a given payload. - /// - /// This function is the entry point for general message passing between chains. - /// - /// A registered chain name on Axelar must be used for `destination_chain`. - fn call_contract( - env: Env, - caller: Address, - destination_chain: String, - destination_address: String, - payload: Bytes, - ); - - /// Checks if a message is approved - /// - /// Determines whether a given message, identified by its `source_chain` and `message_id`, is approved. - /// - /// Returns true if a message with the given `payload_hash` is approved. - fn is_message_approved( - env: Env, - source_chain: String, - message_id: String, - source_address: String, - contract_address: Address, - payload_hash: BytesN<32>, - ) -> bool; - - /// Checks if a message is executed. - /// - /// Returns true if the message is executed, false otherwise. - fn is_message_executed(env: Env, source_chain: String, message_id: String) -> bool; - - /// Validates if a message is approved. If message was in approved status, status is updated to executed to avoid - /// replay. - /// - /// `caller` must be the intended `destination_address` of the contract call for validation to succeed. - fn validate_message( - env: Env, - caller: Address, - source_chain: String, - message_id: String, - source_address: String, - payload_hash: BytesN<32>, - ) -> bool; - +pub trait AxelarGatewayInterface: AxelarGatewayMessagingInterface + UpgradeableInterface { /// Approves a collection of messages. fn approve_messages( env: Env, diff --git a/contracts/axelar-gateway/src/lib.rs b/contracts/axelar-gateway/src/lib.rs index 43c0d611..cf07afd5 100644 --- a/contracts/axelar-gateway/src/lib.rs +++ b/contracts/axelar-gateway/src/lib.rs @@ -6,9 +6,11 @@ extern crate std; pub mod error; +pub mod executable; +mod messaging_interface; pub mod types; +pub use messaging_interface::{AxelarGatewayMessagingClient, AxelarGatewayMessagingInterface}; -pub mod executable; mod interface; #[cfg(all(target_family = "wasm", feature = "testutils"))] diff --git a/contracts/axelar-gateway/src/messaging_interface.rs b/contracts/axelar-gateway/src/messaging_interface.rs new file mode 100644 index 00000000..a418c65a --- /dev/null +++ b/contracts/axelar-gateway/src/messaging_interface.rs @@ -0,0 +1,49 @@ +use soroban_sdk::{contractclient, Address, Bytes, BytesN, Env, String}; + +#[contractclient(name = "AxelarGatewayMessagingClient")] +pub trait AxelarGatewayMessagingInterface { + /// Sends a message to the specified destination chain and contarct address with a given payload. + /// + /// This function is the entry point for general message passing between chains. + /// + /// A registered chain name on Axelar must be used for `destination_chain`. + fn call_contract( + env: Env, + caller: Address, + destination_chain: String, + destination_address: String, + payload: Bytes, + ); + + /// Checks if a message is approved + /// + /// Determines whether a given message, identified by its `source_chain` and `message_id`, is approved. + /// + /// Returns true if a message with the given `payload_hash` is approved. + fn is_message_approved( + env: Env, + source_chain: String, + message_id: String, + source_address: String, + contract_address: Address, + payload_hash: BytesN<32>, + ) -> bool; + + /// Checks if a message is executed. + /// + /// Returns true if the message is executed, false otherwise. + fn is_message_executed(env: Env, source_chain: String, message_id: String) -> bool; + + /// Validates if a message is approved. If message was in approved status, status is updated to executed to avoid + /// replay. + /// + /// `caller` must be the intended `destination_address` of the contract call for validation to succeed. + fn validate_message( + env: Env, + caller: Address, + source_chain: String, + message_id: String, + source_address: String, + payload_hash: BytesN<32>, + ) -> bool; +} diff --git a/contracts/example/src/contract.rs b/contracts/example/src/contract.rs index e20f4948..677d3b31 100644 --- a/contracts/example/src/contract.rs +++ b/contracts/example/src/contract.rs @@ -1,6 +1,6 @@ use crate::event; use axelar_gas_service::AxelarGasServiceClient; -use axelar_gateway::AxelarGatewayClient; +use axelar_gateway::AxelarGatewayMessagingClient; use axelar_soroban_std::types::Token; use soroban_sdk::{contract, contractimpl, Address, Bytes, Env, String}; @@ -24,7 +24,7 @@ impl AxelarExecutableInterface for Example { source_address: String, payload: Bytes, ) { - let _ = Self::validate(&env, &source_chain, &message_id, &source_address, &payload); + let _ = Self::validate_message(&env, &source_chain, &message_id, &source_address, &payload); event::executed(&env, source_chain, message_id, source_address, payload); } @@ -51,7 +51,7 @@ impl Example { message: Bytes, gas_token: Token, ) { - let gateway = AxelarGatewayClient::new(&env, &Self::gateway(&env)); + let gateway = AxelarGatewayMessagingClient::new(&env, &Self::gateway(&env)); let gas_service = AxelarGasServiceClient::new(&env, &Self::gas_service(&env)); caller.require_auth(); diff --git a/integration-tests/tests/gmp.rs b/integration-tests/tests/gmp.rs index 5893bed0..6f788f7f 100644 --- a/integration-tests/tests/gmp.rs +++ b/integration-tests/tests/gmp.rs @@ -23,7 +23,7 @@ impl AxelarExecutableInterface for AxelarApp { source_address: String, payload: Bytes, ) { - let _ = Self::validate(&env, &source_chain, &message_id, &source_address, &payload); + let _ = Self::validate_message(&env, &source_chain, &message_id, &source_address, &payload); env.events() .publish((Symbol::new(&env, "executed"),), (payload,));