diff --git a/Cargo.lock b/Cargo.lock index 4d7e2470..73ebda23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "ahash" @@ -378,6 +378,7 @@ dependencies = [ name = "axelar-gateway" version = "0.1.0" dependencies = [ + "axelar-gateway", "axelar-soroban-std", "cfg-if", "ed25519-dalek", @@ -385,6 +386,7 @@ dependencies = [ "hex", "hex-literal", "rand", + "rand_chacha", "soroban-sdk", ] diff --git a/contracts/axelar-gateway/Cargo.toml b/contracts/axelar-gateway/Cargo.toml index 43772b77..2778f762 100644 --- a/contracts/axelar-gateway/Cargo.toml +++ b/contracts/axelar-gateway/Cargo.toml @@ -14,9 +14,11 @@ axelar-soroban-std = { workspace = true } cfg-if = { workspace = true } ed25519-dalek = { version = "^2.1", default-features = false, optional = true } rand = { version = "0.8.5", optional = true } +rand_chacha = "0.3" soroban-sdk = { workspace = true } [dev-dependencies] +axelar-gateway = { workspace = true, features = ["testutils"] } axelar-soroban-std = { workspace = true, features = ["testutils"] } ed25519-dalek = { version = "^2.1" } goldie = { workspace = true } diff --git a/contracts/axelar-gateway/src/auth.rs b/contracts/axelar-gateway/src/auth.rs index cc823258..ee7c71f1 100644 --- a/contracts/axelar-gateway/src/auth.rs +++ b/contracts/axelar-gateway/src/auth.rs @@ -1,9 +1,10 @@ use crate::error::ContractError; use crate::types::{ProofSignature, ProofSigner, WeightedSigner}; use axelar_soroban_std::ensure; +use axelar_soroban_std::events::Event; use soroban_sdk::{crypto::Hash, Bytes, BytesN, Env, Vec}; -use crate::event; +use crate::event::SignersRotatedEvent; use crate::storage_types::DataKey; use crate::types::{Proof, WeightedSigners}; @@ -104,7 +105,11 @@ pub fn rotate_signers( &new_epoch, ); - event::rotate_signers(env, new_epoch, new_signers_hash); + SignersRotatedEvent { + epoch: new_epoch, + signers_hash: new_signers_hash, + } + .emit(env); Ok(()) } diff --git a/contracts/axelar-gateway/src/contract.rs b/contracts/axelar-gateway/src/contract.rs index 21978cbc..dc83bd43 100644 --- a/contracts/axelar-gateway/src/contract.rs +++ b/contracts/axelar-gateway/src/contract.rs @@ -1,9 +1,11 @@ +use crate::auth; use crate::error::ContractError; +use crate::event::{ContractCalledEvent, MessageApprovedEvent, MessageExecutedEvent}; 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}; +use axelar_soroban_std::events::Event; use axelar_soroban_std::ttl::extend_instance_ttl; use axelar_soroban_std::{ensure, interfaces, Operatable, Ownable, Upgradable}; use soroban_sdk::xdr::ToXdr; @@ -51,14 +53,14 @@ impl AxelarGatewayMessagingInterface for AxelarGateway { let payload_hash = env.crypto().keccak256(&payload).into(); - event::call_contract( - &env, + ContractCalledEvent { caller, destination_chain, destination_address, payload, payload_hash, - ); + } + .emit(&env); } fn is_message_approved( @@ -120,7 +122,7 @@ impl AxelarGatewayMessagingInterface for AxelarGateway { &MessageApprovalValue::Executed, ); - event::execute_message(&env, message); + MessageExecutedEvent { message }.emit(&env); return true; } @@ -128,6 +130,7 @@ impl AxelarGatewayMessagingInterface for AxelarGateway { false } } + #[contractimpl] impl AxelarGatewayInterface for AxelarGateway { fn approve_messages( @@ -161,7 +164,7 @@ impl AxelarGatewayInterface for AxelarGateway { &Self::message_approval_hash(&env, message.clone()), ); - event::approve_message(&env, message); + MessageApprovedEvent { message }.emit(&env); } extend_instance_ttl(&env); diff --git a/contracts/axelar-gateway/src/event.rs b/contracts/axelar-gateway/src/event.rs index 4d11ac38..1a2c9692 100644 --- a/contracts/axelar-gateway/src/event.rs +++ b/contracts/axelar-gateway/src/event.rs @@ -1,35 +1,97 @@ use crate::types::Message; -use soroban_sdk::{Address, Bytes, BytesN, Env, String, Symbol}; - -pub fn call_contract( - env: &Env, - caller: Address, - destination_chain: String, - destination_address: String, - payload: Bytes, - payload_hash: BytesN<32>, -) { - let topics = ( - Symbol::new(env, "contract_called"), - caller, - destination_chain, - destination_address, - payload_hash, - ); - env.events().publish(topics, payload); -} - -pub fn approve_message(env: &Env, message: Message) { - let topics = (Symbol::new(env, "message_approved"), message); - env.events().publish(topics, ()); -} - -pub fn execute_message(env: &Env, message: Message) { - let topics = (Symbol::new(env, "message_executed"), message); - env.events().publish(topics, ()); -} - -pub fn rotate_signers(env: &Env, epoch: u64, signers_hash: BytesN<32>) { - let topics = (Symbol::new(env, "signers_rotated"), epoch, signers_hash); - env.events().publish(topics, ()); + +use core::fmt::Debug; + +use axelar_soroban_std::events::Event; +use cfg_if::cfg_if; +use soroban_sdk::{Address, Bytes, BytesN, Env, IntoVal, String, Symbol, Topics, Val, Vec}; + +#[derive(Debug, PartialEq, Eq)] +pub struct ContractCalledEvent { + pub caller: Address, + pub destination_chain: String, + pub destination_address: String, + pub payload: Bytes, + pub payload_hash: BytesN<32>, +} + +#[derive(Debug, PartialEq, Eq)] +pub struct MessageApprovedEvent { + pub message: Message, +} + +#[derive(Debug, PartialEq, Eq)] +pub struct MessageExecutedEvent { + pub message: Message, +} + +#[derive(Debug, PartialEq, Eq)] +pub struct SignersRotatedEvent { + pub epoch: u64, + pub signers_hash: BytesN<32>, +} + +impl Event for ContractCalledEvent { + fn topics(&self, env: &Env) -> impl Topics + Debug { + ( + Symbol::new(env, "contract_called"), + self.caller.to_val(), + self.destination_chain.to_val(), + self.destination_address.to_val(), + self.payload_hash.to_val(), + ) + } + + fn data(&self, _env: &Env) -> impl IntoVal + Debug { + (self.payload.to_val(),) + } +} + +impl Event for MessageApprovedEvent { + fn topics(&self, env: &Env) -> impl Topics + Debug { + (Symbol::new(env, "message_approved"), self.message.clone()) + } + + fn data(&self, env: &Env) -> impl IntoVal + Debug { + Vec::::new(env) + } +} + +impl Event for MessageExecutedEvent { + fn topics(&self, env: &Env) -> impl Topics + Debug { + (Symbol::new(env, "message_executed"), self.message.clone()) + } + + fn data(&self, env: &Env) -> impl IntoVal + Debug { + Vec::::new(env) + } +} + +impl Event for SignersRotatedEvent { + fn topics(&self, env: &Env) -> impl Topics + Debug { + ( + Symbol::new(env, "signers_rotated"), + self.epoch, + self.signers_hash.to_val(), + ) + } + + fn data(&self, env: &Env) -> impl IntoVal + Debug { + Vec::::new(env) + } +} + +cfg_if! { + if #[cfg(any(test, feature = "testutils"))] { + use axelar_soroban_std::impl_event_testutils; + + impl_event_testutils!( + ContractCalledEvent, + (Symbol, Address, String, String, BytesN<32>), + (Bytes) + ); + impl_event_testutils!(MessageApprovedEvent, (Symbol, Message), ()); + impl_event_testutils!(MessageExecutedEvent, (Symbol, Message), ()); + impl_event_testutils!(SignersRotatedEvent, (Symbol, u64, BytesN<32>), ()); + } } diff --git a/contracts/axelar-gateway/src/lib.rs b/contracts/axelar-gateway/src/lib.rs index 4234ac48..48237d8a 100644 --- a/contracts/axelar-gateway/src/lib.rs +++ b/contracts/axelar-gateway/src/lib.rs @@ -1,7 +1,7 @@ #![no_std] // Allows using std (and its macros) in test modules -#[cfg(test)] +#[cfg(any(test, feature = "testutils"))] #[macro_use] extern crate std; @@ -24,7 +24,7 @@ cfg_if::cfg_if! { pub use interface::{AxelarGatewayClient, AxelarGatewayInterface}; } else { mod auth; - mod event; + pub mod event; mod storage_types; mod contract; diff --git a/contracts/axelar-gateway/src/testutils.rs b/contracts/axelar-gateway/src/testutils.rs index 2ca5fd1d..1d997db7 100644 --- a/contracts/axelar-gateway/src/testutils.rs +++ b/contracts/axelar-gateway/src/testutils.rs @@ -4,6 +4,7 @@ use crate::auth::{self, epoch}; use crate::{AxelarGateway, AxelarGatewayClient}; use axelar_soroban_std::{assert_last_emitted_event, assert_ok}; use ed25519_dalek::{Signature, Signer, SigningKey}; +use rand::distributions::{Alphanumeric, DistString}; use rand::Rng; use soroban_sdk::Symbol; @@ -16,9 +17,6 @@ use crate::types::{ use axelar_soroban_std::traits::IntoVec; -const DESTINATION_CHAIN: &str = "ethereum"; -const DESTINATION_ADDRESS: &str = "0x4EFE356BEDeCC817cb89B4E9b796dB8bC188DC59"; - #[derive(Clone, Debug)] pub struct TestSignerSet { pub signer_keys: std::vec::Vec, @@ -59,8 +57,19 @@ pub fn get_approve_hash(env: &Env, messages: Vec) -> BytesN<32> { .into() } +pub fn deterministic_rng() -> rand_chacha::ChaCha20Rng { + use rand::SeedableRng; + rand_chacha::ChaCha20Rng::seed_from_u64(42) +} + pub fn generate_test_message(env: &Env) -> (Message, Bytes) { - let mut rng = rand::thread_rng(); + generate_test_message_with_rng(env, rand::thread_rng()) +} + +pub fn generate_test_message_with_rng( + env: &Env, + mut rng: impl Rng + rand::CryptoRng, +) -> (Message, Bytes) { let len = rng.gen_range(0..20); let mut payload = std::vec![0u8; len]; rng.fill(&mut payload[..]); @@ -69,9 +78,9 @@ pub fn generate_test_message(env: &Env) -> (Message, Bytes) { ( Message { - source_chain: String::from_str(env, DESTINATION_CHAIN), - message_id: String::from_str(env, "test"), - source_address: String::from_str(env, DESTINATION_ADDRESS), + source_chain: String::from_str(env, &Alphanumeric.sample_string(&mut rng, 10)), + message_id: String::from_str(env, &Alphanumeric.sample_string(&mut rng, 16)), + source_address: String::from_str(env, &Alphanumeric.sample_string(&mut rng, 42)), contract_address: Address::generate(env), payload_hash: env.crypto().keccak256(&payload).into(), }, @@ -88,8 +97,15 @@ pub fn generate_signers_set( num_signers: u32, domain_separator: BytesN<32>, ) -> TestSignerSet { - let mut rng = rand::thread_rng(); + generate_signers_set_with_rng(env, num_signers, domain_separator, rand::thread_rng()) +} +pub fn generate_signers_set_with_rng( + env: &Env, + num_signers: u32, + domain_separator: BytesN<32>, + mut rng: impl Rng + rand::CryptoRng, +) -> TestSignerSet { let mut signer_keypair: std::vec::Vec<_> = (0..num_signers) .map(|_| { let signing_key = SigningKey::generate(&mut rng); diff --git a/contracts/axelar-gateway/tests/gateway.rs b/contracts/axelar-gateway/tests/gateway.rs index ca2d8671..29d071d9 100644 --- a/contracts/axelar-gateway/tests/gateway.rs +++ b/contracts/axelar-gateway/tests/gateway.rs @@ -1,17 +1,20 @@ use axelar_gateway::error::ContractError; +use axelar_gateway::event::{ + ContractCalledEvent, MessageApprovedEvent, MessageExecutedEvent, SignersRotatedEvent, +}; #[cfg(any(test, feature = "testutils"))] use axelar_gateway::testutils::{ - generate_proof, generate_signers_set, generate_test_message, get_approve_hash, randint, + deterministic_rng, generate_proof, generate_signers_set, generate_signers_set_with_rng, + generate_test_message, generate_test_message_with_rng, get_approve_hash, randint, }; use axelar_gateway::types::Message; use axelar_soroban_std::{ - assert_contract_err, assert_invocation, assert_invoke_auth_err, assert_invoke_auth_ok, - assert_last_emitted_event, + assert_contract_err, assert_invocation, assert_invoke_auth_err, assert_invoke_auth_ok, events, }; use soroban_sdk::{ bytes, testutils::{Address as _, Events}, - vec, Address, BytesN, String, Symbol, + vec, Address, BytesN, String, }; mod utils; @@ -39,26 +42,10 @@ fn call_contract() { &user, &client.address, "call_contract", - ( - &user, - destination_chain.clone(), - destination_address.clone(), - payload.clone(), - ), + (&user, destination_chain, destination_address, payload), ); - assert_last_emitted_event( - &env, - &client.address, - ( - Symbol::new(&env, "contract_called"), - user, - destination_chain, - destination_address, - env.crypto().keccak256(&payload), - ), - payload, - ); + goldie::assert!(events::fmt_last_emitted_event::(&env)); } #[test] @@ -110,7 +97,7 @@ fn validate_message() { #[test] fn approve_message() { let (env, signers, client) = setup_env(1, randint(1, 10)); - let (message, _) = generate_test_message(&env); + let (message, _) = generate_test_message_with_rng(&env, deterministic_rng()); let Message { source_chain, message_id, @@ -119,18 +106,13 @@ fn approve_message() { payload_hash, } = message.clone(); - let messages = vec![&env, message.clone()]; + let messages = vec![&env, message]; let data_hash = get_approve_hash(&env, messages.clone()); let proof = generate_proof(&env, data_hash, signers); client.approve_messages(&messages, &proof); - assert_last_emitted_event( - &env, - &client.address, - (Symbol::new(&env, "message_approved"), message.clone()), - (), - ); + goldie::assert!(events::fmt_last_emitted_event::(&env)); let is_approved = client.is_message_approved( &source_chain, @@ -140,6 +122,24 @@ fn approve_message() { &payload_hash, ); assert!(is_approved); +} + +#[test] +fn execute_approved_message() { + let (env, signers, client) = setup_env(1, randint(1, 10)); + let (message, _) = generate_test_message_with_rng(&env, deterministic_rng()); + let Message { + source_chain, + message_id, + source_address, + contract_address, + payload_hash, + } = message.clone(); + + let messages = vec![&env, message]; + let data_hash = get_approve_hash(&env, messages.clone()); + let proof = generate_proof(&env, data_hash, signers); + client.approve_messages(&messages, &proof); let approved = assert_invoke_auth_ok!( contract_address, @@ -153,12 +153,7 @@ fn approve_message() { ); assert!(approved); - assert_last_emitted_event( - &env, - &client.address, - (Symbol::new(&env, "message_executed"), message), - (), - ); + goldie::assert!(events::fmt_last_emitted_event::(&env)); let is_approved = client.is_message_approved( &source_chain, @@ -224,63 +219,66 @@ fn approve_messages_skip_duplicate_message() { fn rotate_signers() { let (env, signers, client) = setup_env(1, 5); - let new_signers = generate_signers_set(&env, 5, signers.domain_separator.clone()); + let new_signers = generate_signers_set_with_rng( + &env, + 5, + signers.domain_separator.clone(), + deterministic_rng(), + ); let data_hash = new_signers.signers.signers_rotation_hash(&env); let proof = generate_proof(&env, data_hash, signers); let bypass_rotation_delay = false; - let new_epoch: u64 = client.epoch() + 1; client.rotate_signers(&new_signers.signers, &proof, &bypass_rotation_delay); - assert_last_emitted_event( + goldie::assert!(events::fmt_last_emitted_event::(&env)); +} + +#[test] +fn approve_messages_after_rotation() { + let (env, signers, client) = setup_env(1, 5); + + let new_signers = generate_signers_set_with_rng( &env, - &client.address, - ( - Symbol::new(&env, "signers_rotated"), - new_epoch, - new_signers.signers.hash(&env), - ), - (), + 5, + signers.domain_separator.clone(), + deterministic_rng(), ); + let data_hash = new_signers.signers.signers_rotation_hash(&env); + let proof = generate_proof(&env, data_hash, signers); + let bypass_rotation_delay = false; - let (message, _) = generate_test_message(&env); - let messages = vec![&env, message.clone()]; + client.rotate_signers(&new_signers.signers, &proof, &bypass_rotation_delay); + + let (message, _) = generate_test_message_with_rng(&env, deterministic_rng()); + let messages = vec![&env, message]; let data_hash = get_approve_hash(&env, messages.clone()); let proof = generate_proof(&env, data_hash, new_signers); + client.approve_messages(&messages, &proof); - assert_last_emitted_event( - &env, - &client.address, - (Symbol::new(&env, "message_approved"), message), - (), - ); + goldie::assert!(events::fmt_last_emitted_event::(&env)); } #[test] fn rotate_signers_bypass_rotation_delay() { let (env, signers, client) = setup_env(1, 5); - let new_signers = generate_signers_set(&env, 5, signers.domain_separator.clone()); + let new_signers = generate_signers_set_with_rng( + &env, + 5, + signers.domain_separator.clone(), + deterministic_rng(), + ); let data_hash = new_signers.signers.signers_rotation_hash(&env); let proof = generate_proof(&env, data_hash, signers); let bypass_rotation_delay = true; - let new_epoch: u64 = client.epoch() + 1; assert_invoke_auth_ok!( client.operator(), client.try_rotate_signers(&new_signers.signers, &proof, &bypass_rotation_delay) ); - assert_last_emitted_event( - &env, - &client.address, - ( - Symbol::new(&env, "signers_rotated"), - new_epoch, - new_signers.signers.hash(&env), - ), - (), - ); + goldie::assert!(events::fmt_last_emitted_event::(&env)); } #[test] diff --git a/contracts/axelar-gateway/tests/testdata/approve_message.golden b/contracts/axelar-gateway/tests/testdata/approve_message.golden new file mode 100644 index 00000000..ca44d50d --- /dev/null +++ b/contracts/axelar-gateway/tests/testdata/approve_message.golden @@ -0,0 +1,3 @@ +contract: Contract(CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M) +topics: (Symbol(message_approved), Message { source_chain: String(GyKqKWL06c), message_id: String(eEcXxGu98ZnxuVEI), source_address: String(Rio2MfZ6FAeTrXvJnvvmWvMIS10fFjmfpPkFPLy7aR), contract_address: Contract(CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4), payload_hash: BytesN<32>(160, 25, 21, 204, 150, 24, 176, 125, 78, 101, 121, 85, 21, 33, 225, 157, 173, 108, 218, 34, 118, 36, 49, 164, 191, 187, 162, 107, 156, 177, 122, 148) }) +data: () \ No newline at end of file diff --git a/contracts/axelar-gateway/tests/testdata/approve_messages_after_rotation.golden b/contracts/axelar-gateway/tests/testdata/approve_messages_after_rotation.golden new file mode 100644 index 00000000..ca44d50d --- /dev/null +++ b/contracts/axelar-gateway/tests/testdata/approve_messages_after_rotation.golden @@ -0,0 +1,3 @@ +contract: Contract(CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M) +topics: (Symbol(message_approved), Message { source_chain: String(GyKqKWL06c), message_id: String(eEcXxGu98ZnxuVEI), source_address: String(Rio2MfZ6FAeTrXvJnvvmWvMIS10fFjmfpPkFPLy7aR), contract_address: Contract(CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4), payload_hash: BytesN<32>(160, 25, 21, 204, 150, 24, 176, 125, 78, 101, 121, 85, 21, 33, 225, 157, 173, 108, 218, 34, 118, 36, 49, 164, 191, 187, 162, 107, 156, 177, 122, 148) }) +data: () \ No newline at end of file diff --git a/contracts/axelar-gateway/tests/testdata/call_contract.golden b/contracts/axelar-gateway/tests/testdata/call_contract.golden new file mode 100644 index 00000000..59cad608 --- /dev/null +++ b/contracts/axelar-gateway/tests/testdata/call_contract.golden @@ -0,0 +1,3 @@ +contract: Contract(CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M) +topics: (Symbol(contract_called), Contract(CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4), String(ethereum), String(0x4EFE356BEDeCC817cb89B4E9b796dB8bC188DC59), BytesN<32>(86, 87, 13, 226, 135, 215, 60, 209, 203, 96, 146, 187, 143, 222, 230, 23, 57, 116, 149, 95, 222, 243, 69, 174, 87, 158, 233, 244, 117, 234, 116, 50)) +data: (Bytes(18, 52)) \ No newline at end of file diff --git a/contracts/axelar-gateway/tests/testdata/execute_approved_message.golden b/contracts/axelar-gateway/tests/testdata/execute_approved_message.golden new file mode 100644 index 00000000..5d59a53a --- /dev/null +++ b/contracts/axelar-gateway/tests/testdata/execute_approved_message.golden @@ -0,0 +1,3 @@ +contract: Contract(CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M) +topics: (Symbol(message_executed), Message { source_chain: String(GyKqKWL06c), message_id: String(eEcXxGu98ZnxuVEI), source_address: String(Rio2MfZ6FAeTrXvJnvvmWvMIS10fFjmfpPkFPLy7aR), contract_address: Contract(CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4), payload_hash: BytesN<32>(160, 25, 21, 204, 150, 24, 176, 125, 78, 101, 121, 85, 21, 33, 225, 157, 173, 108, 218, 34, 118, 36, 49, 164, 191, 187, 162, 107, 156, 177, 122, 148) }) +data: () \ No newline at end of file diff --git a/contracts/axelar-gateway/tests/testdata/rotate_signers.golden b/contracts/axelar-gateway/tests/testdata/rotate_signers.golden new file mode 100644 index 00000000..2da0c3f3 --- /dev/null +++ b/contracts/axelar-gateway/tests/testdata/rotate_signers.golden @@ -0,0 +1,3 @@ +contract: Contract(CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M) +topics: (Symbol(signers_rotated), 2, BytesN<32>(79, 125, 7, 61, 238, 189, 252, 176, 48, 32, 79, 176, 203, 92, 149, 125, 152, 60, 101, 150, 252, 142, 6, 1, 129, 237, 53, 148, 200, 179, 94, 61)) +data: () \ No newline at end of file diff --git a/contracts/axelar-gateway/tests/testdata/rotate_signers_bypass_rotation_delay.golden b/contracts/axelar-gateway/tests/testdata/rotate_signers_bypass_rotation_delay.golden new file mode 100644 index 00000000..2da0c3f3 --- /dev/null +++ b/contracts/axelar-gateway/tests/testdata/rotate_signers_bypass_rotation_delay.golden @@ -0,0 +1,3 @@ +contract: Contract(CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M) +topics: (Symbol(signers_rotated), 2, BytesN<32>(79, 125, 7, 61, 238, 189, 252, 176, 48, 32, 79, 176, 203, 92, 149, 125, 152, 60, 101, 150, 252, 142, 6, 1, 129, 237, 53, 148, 200, 179, 94, 61)) +data: () \ No newline at end of file diff --git a/contracts/example/tests/test.rs b/contracts/example/tests/test.rs index 8d52214c..3dac827a 100644 --- a/contracts/example/tests/test.rs +++ b/contracts/example/tests/test.rs @@ -136,7 +136,7 @@ fn gmp_example() { destination_address, payload_hash.clone(), ), - payload.clone(), + (payload.to_val(),), ); // Axelar hub signs the message approval, Signing message approval for destination