From eb61af10a1b74075b83dc63c858987faf16b4421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Wed, 8 Jan 2025 09:38:14 +0200 Subject: [PATCH 1/2] esdt-safe: add unit tests --- esdt-safe/tests/esdt_safe_blackbox_test.rs | 161 +++++++++++++++++++++ 1 file changed, 161 insertions(+) diff --git a/esdt-safe/tests/esdt_safe_blackbox_test.rs b/esdt-safe/tests/esdt_safe_blackbox_test.rs index c3e3e06e..8ad025f1 100644 --- a/esdt-safe/tests/esdt_safe_blackbox_test.rs +++ b/esdt-safe/tests/esdt_safe_blackbox_test.rs @@ -1343,3 +1343,164 @@ fn withdraw_transaction_fees_test() { "accumulated_transaction_fees should be zero after withdrawal" ); } + +#[test] +fn esdt_safe_reduce_max_tx_batch_size_test() { + let mut state = EsdtSafeTestState::new(); + state.multisig_deploy(); + state.safe_deploy(); + + state.world.set_esdt_balance( + MULTISIG_ADDRESS, + b"TOKEN-WITH", + BigUint::from(10_000_000u64), + ); + + state.config_esdtsafe(); + + // Batch size is default 10 + state + .world + .tx() + .from(BRIDGED_TOKENS_WRAPPER_ADDRESS) + .to(ESDT_SAFE_ADDRESS) + .typed(esdt_safe_proxy::EsdtSafeProxy) + .create_transaction( + EthAddress { + raw_addr: ManagedByteArray::new_from_bytes(b"01020304050607080910"), + }, + OptionalValue::>::None, + ) + .single_esdt(&TOKEN_ID.into(), 0, &BigUint::from(10u64)) + .run(); + + state + .world + .tx() + .from(BRIDGED_TOKENS_WRAPPER_ADDRESS) + .to(ESDT_SAFE_ADDRESS) + .typed(esdt_safe_proxy::EsdtSafeProxy) + .create_transaction( + EthAddress { + raw_addr: ManagedByteArray::new_from_bytes(b"01020304050607080910"), + }, + OptionalValue::>::None, + ) + .single_esdt(&TOKEN_ID.into(), 0, &BigUint::from(10u64)) + .run(); + + state + .world + .tx() + .from(BRIDGED_TOKENS_WRAPPER_ADDRESS) + .to(ESDT_SAFE_ADDRESS) + .typed(esdt_safe_proxy::EsdtSafeProxy) + .create_transaction( + EthAddress { + raw_addr: ManagedByteArray::new_from_bytes(b"01020304050607080910"), + }, + OptionalValue::>::None, + ) + .single_esdt(&TOKEN_ID.into(), 0, &BigUint::from(10u64)) + .run(); + + state + .world + .tx() + .from(BRIDGED_TOKENS_WRAPPER_ADDRESS) + .to(ESDT_SAFE_ADDRESS) + .typed(esdt_safe_proxy::EsdtSafeProxy) + .create_transaction( + EthAddress { + raw_addr: ManagedByteArray::new_from_bytes(b"01020304050607080910"), + }, + OptionalValue::>::None, + ) + .single_esdt(&TOKEN_ID.into(), 0, &BigUint::from(10u64)) + .run(); + + //get_batch_status + let batch_id = 1u64; + let batch_status = state + .world + .tx() + .from(BRIDGED_TOKENS_WRAPPER_ADDRESS) + .to(ESDT_SAFE_ADDRESS) + .typed(esdt_safe_proxy::EsdtSafeProxy) + .get_batch_status(batch_id) + .returns(ReturnsResult) + .run(); + + assert_eq!( + batch_status, + BatchStatus::PartiallyFull { + end_block_nonce: 100, + tx_ids: ManagedVec::from(vec![1u64, 2u64, 3u64, 4u64]) + }, + "Incorrect batch status" + ); + + let new_max_batch_status = 2usize; + state + .world + .tx() + .from(MULTISIG_ADDRESS) + .to(ESDT_SAFE_ADDRESS) + .typed(esdt_safe_proxy::EsdtSafeProxy) + .set_max_tx_batch_size(new_max_batch_status) + .run(); + + state + .world + .tx() + .from(BRIDGED_TOKENS_WRAPPER_ADDRESS) + .to(ESDT_SAFE_ADDRESS) + .typed(esdt_safe_proxy::EsdtSafeProxy) + .create_transaction( + EthAddress { + raw_addr: ManagedByteArray::new_from_bytes(b"01020304050607080910"), + }, + OptionalValue::>::None, + ) + .single_esdt(&TOKEN_ID.into(), 0, &BigUint::from(10u64)) + .run(); + + //First batch should be full + let batch_id = 1u64; + let batch_status = state + .world + .tx() + .from(BRIDGED_TOKENS_WRAPPER_ADDRESS) + .to(ESDT_SAFE_ADDRESS) + .typed(esdt_safe_proxy::EsdtSafeProxy) + .get_batch_status(batch_id) + .returns(ReturnsResult) + .run(); + + assert_eq!( + batch_status, + BatchStatus::WaitingForSignatures, + "Incorrect batch status" + ); + + //A new batch should be created + let batch_id = 2u64; + let batch_status = state + .world + .tx() + .from(BRIDGED_TOKENS_WRAPPER_ADDRESS) + .to(ESDT_SAFE_ADDRESS) + .typed(esdt_safe_proxy::EsdtSafeProxy) + .get_batch_status(batch_id) + .returns(ReturnsResult) + .run(); + + assert_eq!( + batch_status, + BatchStatus::PartiallyFull { + end_block_nonce: 100, + tx_ids: ManagedVec::from(vec![5u64]) + }, + "Incorrect batch status" + ); +} From 479dff9f8af9f2ad174e3a042ab99cf643a9eb6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Costin=20Caraba=C8=99?= Date: Wed, 8 Jan 2025 15:26:49 +0200 Subject: [PATCH 2/2] Add unit tests for bridge-proxy --- .../tests/bridge_proxy_blackbox_test.rs | 175 +++++++++++++++++- 1 file changed, 174 insertions(+), 1 deletion(-) diff --git a/bridge-proxy/tests/bridge_proxy_blackbox_test.rs b/bridge-proxy/tests/bridge_proxy_blackbox_test.rs index b0087c2b..96174b23 100644 --- a/bridge-proxy/tests/bridge_proxy_blackbox_test.rs +++ b/bridge-proxy/tests/bridge_proxy_blackbox_test.rs @@ -8,7 +8,7 @@ use bridge_proxy::config::ProxyTrait as _; use crowdfunding_esdt::crowdfunding_esdt_proxy; use multiversx_sc::codec::NestedEncode; use multiversx_sc::contract_base::ManagedSerializer; -use multiversx_sc::sc_print; +use multiversx_sc::imports::MultiValue2; use multiversx_sc::types::{ EgldOrEsdtTokenIdentifier, EsdtTokenPayment, ManagedOption, MultiValueEncoded, ReturnsNewAddress, ReturnsResult, TestAddress, TestSCAddress, TestTokenIdentifier, @@ -25,6 +25,7 @@ use multiversx_sc::{ ManagedByteArray, ManagedVec, TokenIdentifier, }, }; +use multiversx_sc::{require, sc_print}; use multiversx_sc_scenario::imports::MxscPath; use multiversx_sc_scenario::{ api::StaticApi, @@ -1105,3 +1106,175 @@ fn bridge_proxy_refund_tx_test() { .check_account(BRIDGE_PROXY_ADDRESS) .check_storage("str:highestTxId", "1"); } + +#[test] +fn bridge_proxy_double_execute_same_tx_test() { + let mut test = BridgeProxyTestState::new(); + test.multisig_deploy(); + + test.deploy_bridge_proxy(); + test.deploy_crowdfunding(); + test.config_bridge(); + + let mut args = ManagedVec::new(); + + let call_data: CallData = CallData { + endpoint: ManagedBuffer::from("fund"), + gas_limit: GAS_LIMIT, + args: ManagedOption::some(args), + }; + + let call_data: ManagedBuffer = + ManagedSerializer::new().top_encode_to_managed_buffer(&call_data); + + let eth_tx = EthTransaction { + from: EthAddress { + raw_addr: ManagedByteArray::new_from_bytes(b"01020304050607080910"), + }, + to: ManagedAddress::from(CROWDFUNDING_ADDRESS.eval_to_array()), + token_id: BRIDGE_TOKEN_ID.into(), + amount: BigUint::from(500u64), + tx_nonce: 1u64, + call_data: ManagedOption::some(call_data), + }; + + test.world + .tx() + .from(MULTI_TRANSFER_ADDRESS) + .to(BRIDGE_PROXY_ADDRESS) + .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) + .deposit(ð_tx, 1u64) + .egld_or_single_esdt( + &EgldOrEsdtTokenIdentifier::esdt(BRIDGE_TOKEN_ID), + 0, + &BigUint::from(500u64), + ) + .run(); + + test.world + .query() + .to(BRIDGE_PROXY_ADDRESS) + .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) + .get_pending_transaction_by_id(1u32) + .returns(ExpectValue(eth_tx)) + .run(); + + test.world + .tx() + .from(OWNER_ADDRESS) + .to(BRIDGE_PROXY_ADDRESS) + .gas(200_000_000) + .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) + .execute(1u32) + .run(); + + test.world + .query() + .to(CROWDFUNDING_ADDRESS) + .typed(crowdfunding_esdt_proxy::CrowdfundingProxy) + .get_current_funds() + .returns(ExpectValue(500u64)) + .run(); + + test.world + .tx() + .from(OWNER_ADDRESS) + .to(BRIDGE_PROXY_ADDRESS) + .gas(200_000_000) + .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) + .execute(1u32) + .returns(ExpectError(4, "Invalid tx id")) + .run(); +} + +#[test] +fn bridge_proxy_execute_1000_even_tx_test() { + let mut test = BridgeProxyTestState::new(); + test.multisig_deploy(); + + test.deploy_bridge_proxy(); + test.deploy_crowdfunding(); + test.config_bridge(); + + let mut args = ManagedVec::new(); + + let call_data: CallData = CallData { + endpoint: ManagedBuffer::from("fund"), + gas_limit: GAS_LIMIT, + args: ManagedOption::some(args), + }; + + let call_data: ManagedBuffer = + ManagedSerializer::new().top_encode_to_managed_buffer(&call_data); + + let eth_tx = EthTransaction { + from: EthAddress { + raw_addr: ManagedByteArray::new_from_bytes(b"01020304050607080910"), + }, + to: ManagedAddress::from(CROWDFUNDING_ADDRESS.eval_to_array()), + token_id: BRIDGE_TOKEN_ID.into(), + amount: BigUint::from(5u64), + tx_nonce: 1u64, + call_data: ManagedOption::some(call_data), + }; + + for _ in 1..101 { + test.world + .tx() + .from(MULTI_TRANSFER_ADDRESS) + .to(BRIDGE_PROXY_ADDRESS) + .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) + .deposit(ð_tx, 1u64) + .egld_or_single_esdt( + &EgldOrEsdtTokenIdentifier::esdt(BRIDGE_TOKEN_ID), + 0, + &BigUint::from(5u64), + ) + .run(); + } + + for i in 1..101u32 { + test.world + .query() + .to(BRIDGE_PROXY_ADDRESS) + .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) + .get_pending_transaction_by_id(i) + .returns(ExpectValue(eth_tx.clone())) + .run(); + } + + for i in 1..101u32 { + if i % 2 == 1 { + continue; + } + test.world + .tx() + .from(OWNER_ADDRESS) + .to(BRIDGE_PROXY_ADDRESS) + .gas(200_000_000) + .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) + .execute(i) + .run(); + } + test.world + .query() + .to(CROWDFUNDING_ADDRESS) + .typed(crowdfunding_esdt_proxy::CrowdfundingProxy) + .get_current_funds() + .returns(ExpectValue(250u64)) + .run(); + + let pending_txs = test + .world + .query() + .to(BRIDGE_PROXY_ADDRESS) + .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) + .get_pending_transactions() + .returns(ReturnsResult) + .run(); + + for tx in pending_txs { + let (tx_id, actual_tx) = tx.into_tuple(); + assert!(tx_id % 2 == 1); + } +}