From 5f5e40ac1462f72f86793fb4ad697165453e8b8d Mon Sep 17 00:00:00 2001 From: xg95 <77263687+xg95@users.noreply.github.com> Date: Wed, 8 Jul 2026 12:07:15 +0800 Subject: [PATCH 1/2] poc --- contracts/message-transmitter-v2/src/test.rs | 38 ++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/contracts/message-transmitter-v2/src/test.rs b/contracts/message-transmitter-v2/src/test.rs index 2b455f8..7b15aa0 100644 --- a/contracts/message-transmitter-v2/src/test.rs +++ b/contracts/message-transmitter-v2/src/test.rs @@ -971,6 +971,44 @@ fn test_receive_message_fails_with_nonce_already_used() { client.receive_message(&caller, &fixture.message, &fixture.attestation); } +#[test] +fn test_nonce_expiry_allows_message_replay() { + let ctx = setup_contract(); + let client = ctx.client(); + let caller = Address::generate(&ctx.env); + + let _mock_handler_address = ctx.env.register(MockMessageHandler, ()); + let fixture = fixture_valid_message(&ctx.env); + + mock_receive_message_auth( + &ctx.env, + &ctx.contract_id, + &caller, + fixture.message.clone(), + fixture.attestation.clone(), + ); + client.receive_message(&caller, &fixture.message, &fixture.attestation); + + let nonce = MessageV2::get_nonce(&fixture.message).unwrap(); + assert!(client.is_nonce_used(&nonce)); + + let nonce_key = storage::MessageTransmitterStorageKey::UsedNonce(nonce.clone()); + ctx.env.as_contract(&ctx.contract_id, || { + ctx.env.storage().persistent().remove(&nonce_key); + }); + + assert!(!client.is_nonce_used(&nonce)); + + mock_receive_message_auth( + &ctx.env, + &ctx.contract_id, + &caller, + fixture.message.clone(), + fixture.attestation.clone(), + ); + client.receive_message(&caller, &fixture.message, &fixture.attestation); +} + // ============================================================= // Attestable Tests // ============================================================= From af4a4e7bc9794fa9d2f584ba2227357d2449b056 Mon Sep 17 00:00:00 2001 From: xg95 <77263687+xg95@users.noreply.github.com> Date: Wed, 8 Jul 2026 13:13:53 +0800 Subject: [PATCH 2/2] fix --- contracts/message-transmitter-v2/src/test.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/message-transmitter-v2/src/test.rs b/contracts/message-transmitter-v2/src/test.rs index 7b15aa0..dd929e5 100644 --- a/contracts/message-transmitter-v2/src/test.rs +++ b/contracts/message-transmitter-v2/src/test.rs @@ -16,6 +16,7 @@ * limitations under the License. */ use crate::contract::MessageTransmitterV2ContractInitParams; +use crate::storage; use crate::test_utils::{ create_test_message, fixture_invalid_destination_caller_message, fixture_invalid_destination_domain_message, fixture_invalid_version_message,