diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index 1cd3747a..bed0c289 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -17,7 +17,7 @@ permissions: jobs: contracts: name: Contracts - uses: multiversx/mx-sc-actions/.github/workflows/contracts.yml@v3.2.0 + uses: multiversx/mx-sc-actions/.github/workflows/contracts.yml@v3.3.1 with: rust-toolchain: stable secrets: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ebe25691..4547f03a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ permissions: jobs: build: - uses: multiversx/mx-sc-actions/.github/workflows/reproducible-build.yml@v3.2.0 + uses: multiversx/mx-sc-actions/.github/workflows/reproducible-build.yml@v3.3.1 with: - image_tag: v7.0.0 + image_tag: v8.0.1 attach_to_existing_release: true diff --git a/Cargo.lock b/Cargo.lock index e6543f62..6abe7cb2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -528,9 +528,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.160" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0b21006cd1874ae9e650973c565615676dc4a274c965bb0a73796dac838ce4f" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "log" diff --git a/bridge-proxy/scenarios/bridge_proxy_execute_crowdfunding.scen.json b/bridge-proxy/scenarios/bridge_proxy_execute_crowdfunding.scen.json index 60b727a3..92f241d8 100644 --- a/bridge-proxy/scenarios/bridge_proxy_execute_crowdfunding.scen.json +++ b/bridge-proxy/scenarios/bridge_proxy_execute_crowdfunding.scen.json @@ -190,7 +190,8 @@ ], "function": "deposit", "arguments": [ - "0x30313032303330343035303630373038303931300000000000000000050063726f7766756e64696e675f5f5f5f5f5f5f5f5f5f5f0000000d4252494447452d3132333435360000000201f4000000000000000101000000150000000466756e6400000000009896800100000000" + "0x30313032303330343035303630373038303931300000000000000000050063726f7766756e64696e675f5f5f5f5f5f5f5f5f5f5f0000000d4252494447452d3132333435360000000201f4000000000000000101000000150000000466756e6400000000009896800100000000", + "0x01" ], "gasLimit": "5,000,000" }, @@ -226,7 +227,7 @@ "arguments": [ "0x01" ], - "gasLimit": "5,000,000" + "gasLimit": "200000000" }, "expect": { "out": [], diff --git a/bridge-proxy/src/bridge-proxy.rs b/bridge-proxy/src/bridge-proxy.rs index 5c7171c1..90103808 100644 --- a/bridge-proxy/src/bridge-proxy.rs +++ b/bridge-proxy/src/bridge-proxy.rs @@ -1,17 +1,23 @@ #![no_std] use multiversx_sc::imports::*; +use multiversx_sc_modules::ongoing_operation::*; pub mod config; use sc_proxies::bridged_tokens_wrapper_proxy; +use sc_proxies::esdt_safe_proxy; use transaction::{CallData, EthTransaction}; const MIN_GAS_LIMIT_FOR_SC_CALL: u64 = 10_000_000; +const MAX_GAS_LIMIT_FOR_SC_CALL: u64 = 249999999; const DEFAULT_GAS_LIMIT_FOR_REFUND_CALLBACK: u64 = 20_000_000; // 20 million const DELAY_BEFORE_OWNER_CAN_CANCEL_TRANSACTION: u64 = 300; +const MIN_GAS_TO_SAVE_PROGRESS: u64 = 100_000; #[multiversx_sc::contract] pub trait BridgeProxyContract: - config::ConfigModule + multiversx_sc_modules::pause::PauseModule + config::ConfigModule + + multiversx_sc_modules::pause::PauseModule + + multiversx_sc_modules::ongoing_operation::OngoingOperationModule { #[init] fn init(&self, opt_multi_transfer_address: OptionalValue) { @@ -27,7 +33,7 @@ pub trait BridgeProxyContract: #[payable("*")] #[endpoint] - fn deposit(&self, eth_tx: EthTransaction) { + fn deposit(&self, eth_tx: EthTransaction, batch_id: u64) { self.require_not_paused(); let caller = self.blockchain().get_caller(); let payment = self.call_value().single_esdt(); @@ -37,6 +43,7 @@ pub trait BridgeProxyContract: ); let tx_id = self.pending_transactions().push(ð_tx); self.payments(tx_id).set(&payment); + self.batch_id(tx_id).set(batch_id); } #[endpoint(execute)] @@ -65,13 +72,16 @@ pub trait BridgeProxyContract: }; if call_data.endpoint.is_empty() - || call_data.gas_limit == 0 || call_data.gas_limit < MIN_GAS_LIMIT_FOR_SC_CALL + || call_data.gas_limit > MAX_GAS_LIMIT_FOR_SC_CALL { self.finish_execute_gracefully(tx_id); return; } + let gas_left = self.blockchain().get_gas_left(); + require!(gas_left > call_data.gas_limit + DEFAULT_GAS_LIMIT_FOR_REFUND_CALLBACK, "Not enough gas to execute"); + let tx_call = self .tx() .to(&tx.to) @@ -93,7 +103,8 @@ pub trait BridgeProxyContract: tx_call.register_promise(); } - #[endpoint(cancel)] + // TODO: will activate endpoint in a future release + // #[endpoint(cancel)] fn cancel(&self, tx_id: usize) { let tx_start_round = self.ongoing_execution(tx_id).get(); let current_block_round = self.blockchain().get_block_round(); @@ -117,19 +128,51 @@ pub trait BridgeProxyContract: fn refund_transaction(&self, tx_id: usize) { let tx = self.get_pending_transaction_by_id(tx_id); - let payment = self.payments(tx_id).get(); - let esdt_safe_addr = self.bridged_tokens_wrapper_address().get(); + let esdt_safe_contract_address = self.esdt_safe_contract_address().get(); + let unwrapped_token = self.unwrap_token(&tx.token_id, tx_id); + let batch_id = self.batch_id(tx_id).get(); self.tx() - .to(esdt_safe_addr) - .typed(bridged_tokens_wrapper_proxy::BridgedTokensWrapperProxy) - .unwrap_token_create_transaction(&tx.token_id, tx.from, OptionalValue::Some(tx.to)) + .to(esdt_safe_contract_address) + .typed(esdt_safe_proxy::EsdtSafeProxy) + .create_transaction(tx.from, OptionalValue::Some(esdt_safe_proxy::RefundInfo { + address: tx.to, + initial_batch_id: batch_id, + initial_nonce: tx.tx_nonce, + })) + .single_esdt( + &unwrapped_token.token_identifier, + unwrapped_token.token_nonce, + &unwrapped_token.amount, + ) + .sync_call(); + } + + fn unwrap_token(&self, requested_token: &TokenIdentifier, tx_id: usize) -> EsdtTokenPayment { + let payment = self.payments(tx_id).get(); + let bridged_tokens_wrapper_address = self.bridged_tokens_wrapper_address().get(); + + let transfers = self + .tx() + .to(bridged_tokens_wrapper_address) .typed(bridged_tokens_wrapper_proxy::BridgedTokensWrapperProxy) + .unwrap_token(requested_token) .single_esdt( &payment.token_identifier, payment.token_nonce, &payment.amount, ) + .returns(ReturnsBackTransfers) .sync_call(); + + require!( + transfers.total_egld_amount == 0, + "Expected only one esdt payment" + ); + require!( + transfers.esdt_payments.len() == 1, + "Expected only one esdt payment" + ); + transfers.esdt_payments.get(0) } fn finish_execute_gracefully(&self, tx_id: usize) { @@ -143,17 +186,28 @@ pub trait BridgeProxyContract: self.ongoing_execution(tx_id).clear(); } + #[endpoint(updateLowestTxId)] fn update_lowest_tx_id(&self) { let mut new_lowest = self.lowest_tx_id().get(); let len = self.pending_transactions().len(); - while new_lowest < len && self.pending_transactions().item_is_empty(new_lowest) { + self.run_while_it_has_gas(MIN_GAS_TO_SAVE_PROGRESS, || { + if !self.empty_element(new_lowest, len) { + return STOP_OP; + } + new_lowest += 1; - } + + CONTINUE_OP + }); self.lowest_tx_id().set(new_lowest); } + fn empty_element(&self, current_index: usize, len: usize) -> bool { + current_index < len && self.pending_transactions().item_is_empty(current_index) + } + #[view(getPendingTransactionById)] fn get_pending_transaction_by_id(&self, tx_id: usize) -> EthTransaction { self.pending_transactions() diff --git a/bridge-proxy/src/config.rs b/bridge-proxy/src/config.rs index e0741ccc..9712ae91 100644 --- a/bridge-proxy/src/config.rs +++ b/bridge-proxy/src/config.rs @@ -73,6 +73,9 @@ pub trait ConfigModule { #[storage_mapper("payments")] fn payments(&self, tx_id: usize) -> SingleValueMapper>; + #[storage_mapper("batch_id")] + fn batch_id(&self, tx_id: usize) -> SingleValueMapper; + #[view(lowestTxId)] #[storage_mapper("lowest_tx_id")] fn lowest_tx_id(&self) -> SingleValueMapper; diff --git a/bridge-proxy/tests/bridge_proxy_blackbox_test.rs b/bridge-proxy/tests/bridge_proxy_blackbox_test.rs index 66b736a5..12a422ff 100644 --- a/bridge-proxy/tests/bridge_proxy_blackbox_test.rs +++ b/bridge-proxy/tests/bridge_proxy_blackbox_test.rs @@ -272,7 +272,7 @@ fn bridge_proxy_execute_crowdfunding_test() { .from(MULTI_TRANSFER_ADDRESS) .to(BRIDGE_PROXY_ADDRESS) .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) - .deposit(ð_tx) + .deposit(ð_tx, 1u64) .egld_or_single_esdt( &EgldOrEsdtTokenIdentifier::esdt(BRIDGE_TOKEN_ID), 0, @@ -292,6 +292,7 @@ fn bridge_proxy_execute_crowdfunding_test() { .tx() .from(OWNER_ADDRESS) .to(BRIDGE_PROXY_ADDRESS) + .gas(200_000_000) .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) .execute(1u32) .run(); @@ -352,7 +353,7 @@ fn multiple_deposit_test() { .from(MULTI_TRANSFER_ADDRESS) .to(BRIDGE_PROXY_ADDRESS) .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) - .deposit(ð_tx1) + .deposit(ð_tx1, 1u64) .single_esdt( &TokenIdentifier::from(BRIDGE_TOKEN_ID), 0u64, @@ -365,7 +366,7 @@ fn multiple_deposit_test() { .from(MULTI_TRANSFER_ADDRESS) .to(BRIDGE_PROXY_ADDRESS) .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) - .deposit(ð_tx2) + .deposit(ð_tx2, 1u64) .single_esdt( &TokenIdentifier::from(BRIDGE_TOKEN_ID), 0u64, @@ -385,6 +386,7 @@ fn multiple_deposit_test() { .tx() .from(OWNER_ADDRESS) .to(BRIDGE_PROXY_ADDRESS) + .gas(200_000_000) .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) .execute(1u32) .run(); @@ -401,6 +403,7 @@ fn multiple_deposit_test() { .tx() .from(OWNER_ADDRESS) .to(BRIDGE_PROXY_ADDRESS) + .gas(200_000_000) .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) .execute(2u32) .run(); @@ -462,7 +465,7 @@ fn test_lowest_tx_id() { .from(MULTI_TRANSFER_ADDRESS) .to(BRIDGE_PROXY_ADDRESS) .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) - .deposit(tx) + .deposit(tx, 1u64) .single_esdt( &TokenIdentifier::from(BRIDGE_TOKEN_ID), 0u64, @@ -486,6 +489,7 @@ fn test_lowest_tx_id() { .tx() .from(OWNER_ADDRESS) .to(BRIDGE_PROXY_ADDRESS) + .gas(200_000_000) .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) .execute(i) .run(); @@ -506,6 +510,7 @@ fn test_lowest_tx_id() { .tx() .from(OWNER_ADDRESS) .to(BRIDGE_PROXY_ADDRESS) + .gas(200_000_000) .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) .execute(i) .run(); diff --git a/bridge-proxy/wasm/src/lib.rs b/bridge-proxy/wasm/src/lib.rs index dad940d1..bcfd0f92 100644 --- a/bridge-proxy/wasm/src/lib.rs +++ b/bridge-proxy/wasm/src/lib.rs @@ -23,7 +23,7 @@ multiversx_sc_wasm_adapter::endpoints! { upgrade => upgrade deposit => deposit execute => execute - cancel => cancel + updateLowestTxId => update_lowest_tx_id getPendingTransactionById => get_pending_transaction_by_id getPendingTransactions => get_pending_transactions setMultiTransferAddress => set_multi_transfer_contract_address diff --git a/bridged-tokens-wrapper/src/lib.rs b/bridged-tokens-wrapper/src/lib.rs index 11617c5d..eb2e9366 100644 --- a/bridged-tokens-wrapper/src/lib.rs +++ b/bridged-tokens-wrapper/src/lib.rs @@ -247,7 +247,6 @@ pub trait BridgedTokensWrapper: &self, requested_token: TokenIdentifier, to: EthAddress, - opt_refunding_address: OptionalValue, ) { let (payment_token, payment_amount) = self.call_value().single_fungible_esdt(); let universal_token_id = self @@ -261,21 +260,14 @@ pub trait BridgedTokensWrapper: }; let caller = self.blockchain().get_caller(); - let refunding_addr = match opt_refunding_address { - OptionalValue::Some(refunding_addr) => { - require!( - caller == self.bridge_proxy_contract_address().get(), - "Wrong caller for a refund tx" - ); - refunding_addr - } - OptionalValue::None => caller, - }; - self.tx() .to(self.esdt_safe_contract_address().get()) .typed(esdt_safe_proxy::EsdtSafeProxy) - .create_transaction(to, OptionalValue::Some(refunding_addr)) + .create_transaction(to, OptionalValue::Some(esdt_safe_proxy::RefundInfo { + address: caller, + initial_batch_id: 0, + initial_nonce: 0, + })) .single_esdt(&requested_token, 0, &converted_amount) .sync_call(); } @@ -327,22 +319,6 @@ pub trait BridgedTokensWrapper: } } - #[only_owner] - #[endpoint(setBridgeProxyContractAddress)] - fn set_bridge_proxy_contract_address(&self, opt_new_address: OptionalValue) { - match opt_new_address { - OptionalValue::Some(sc_addr) => { - require!( - self.blockchain().is_smart_contract(&sc_addr), - "Invalid bridge proxy contract address" - ); - - self.bridge_proxy_contract_address().set(&sc_addr); - } - OptionalValue::None => self.bridge_proxy_contract_address().clear(), - } - } - #[view(getUniversalBridgedTokenIds)] #[storage_mapper("universalBridgedTokenIds")] fn universal_bridged_token_ids(&self) -> UnorderedSetMapper; @@ -372,7 +348,4 @@ pub trait BridgedTokensWrapper: #[storage_mapper("esdtSafeContractAddress")] fn esdt_safe_contract_address(&self) -> SingleValueMapper; - #[view(getBridgeProxyContractAddress)] - #[storage_mapper("bridgeProxyContractAddress")] - fn bridge_proxy_contract_address(&self) -> SingleValueMapper; } diff --git a/bridged-tokens-wrapper/tests/bridged_tokens_wrapper_whitebox_test.rs b/bridged-tokens-wrapper/tests/bridged_tokens_wrapper_whitebox_test.rs index 538e5896..7cffadc8 100644 --- a/bridged-tokens-wrapper/tests/bridged_tokens_wrapper_whitebox_test.rs +++ b/bridged-tokens-wrapper/tests/bridged_tokens_wrapper_whitebox_test.rs @@ -434,7 +434,6 @@ fn test_unwrap_token_create_transaction_should_fail_case_1() { sc.unwrap_token_create_transaction( managed_token_id!(UNIVERSAL_TOKEN_IDENTIFIER), address, - OptionalValue::None, ); }, |r| r.assert_user_error("Contract is paused"), @@ -472,7 +471,6 @@ fn test_unwrap_token_create_transaction_should_fail_case_2() { sc.unwrap_token_create_transaction( managed_token_id!(UNIVERSAL_TOKEN_IDENTIFIER), address, - OptionalValue::None, ); }, |r| r.assert_user_error("Must pay more than 0 tokens!"), @@ -510,7 +508,6 @@ fn test_unwrap_token_create_transaction_should_fail_case_3() { sc.unwrap_token_create_transaction( managed_token_id!(UNIVERSAL_TOKEN_IDENTIFIER), address, - OptionalValue::None, ); }, |r| r.assert_user_error("Esdt token unavailable"), @@ -583,7 +580,6 @@ fn test_unwrap_token_create_transaction_should_fail_case_4() { sc.unwrap_token_create_transaction( managed_token_id!(UNIVERSAL_TOKEN_IDENTIFIER), address, - OptionalValue::None, ); }, |r| r.assert_user_error("Contract does not have enough funds"), diff --git a/bridged-tokens-wrapper/wasm/src/lib.rs b/bridged-tokens-wrapper/wasm/src/lib.rs index 09edb906..29f9d9c1 100644 --- a/bridged-tokens-wrapper/wasm/src/lib.rs +++ b/bridged-tokens-wrapper/wasm/src/lib.rs @@ -6,9 +6,9 @@ // Init: 1 // Upgrade: 1 -// Endpoints: 21 +// Endpoints: 19 // Async Callback (empty): 1 -// Total number of exported functions: 24 +// Total number of exported functions: 22 #![no_std] @@ -31,13 +31,11 @@ multiversx_sc_wasm_adapter::endpoints! { unwrapToken => unwrap_token unwrapTokenCreateTransaction => unwrap_token_create_transaction setEsdtSafeContractAddress => set_esdt_safe_contract_address - setBridgeProxyContractAddress => set_bridge_proxy_contract_address getUniversalBridgedTokenIds => universal_bridged_token_ids getTokenLiquidity => token_liquidity getChainSpecificToUniversalMapping => chain_specific_to_universal_mapping getchainSpecificTokenIds => chain_specific_token_ids getEsdtSafeContractAddress => esdt_safe_contract_address - getBridgeProxyContractAddress => bridge_proxy_contract_address pause => pause_endpoint unpause => unpause_endpoint isPaused => paused_status diff --git a/common/sc-proxies/src/bridge_proxy_contract_proxy.rs b/common/sc-proxies/src/bridge_proxy_contract_proxy.rs index 842e5d22..768889b6 100644 --- a/common/sc-proxies/src/bridge_proxy_contract_proxy.rs +++ b/common/sc-proxies/src/bridge_proxy_contract_proxy.rs @@ -87,13 +87,16 @@ where { pub fn deposit< Arg0: ProxyArg>, + Arg1: ProxyArg, >( self, eth_tx: Arg0, + batch_id: Arg1, ) -> TxTypedCall { self.wrapped_tx .raw_call("deposit") .argument(ð_tx) + .argument(&batch_id) .original_result() } @@ -110,16 +113,12 @@ where .original_result() } - pub fn cancel< - Arg0: ProxyArg, - >( + pub fn update_lowest_tx_id( self, - tx_id: Arg0, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) - .raw_call("cancel") - .argument(&tx_id) + .raw_call("updateLowestTxId") .original_result() } diff --git a/common/sc-proxies/src/bridged_tokens_wrapper_proxy.rs b/common/sc-proxies/src/bridged_tokens_wrapper_proxy.rs index 852e4057..df5b7a63 100644 --- a/common/sc-proxies/src/bridged_tokens_wrapper_proxy.rs +++ b/common/sc-proxies/src/bridged_tokens_wrapper_proxy.rs @@ -206,18 +206,15 @@ where pub fn unwrap_token_create_transaction< Arg0: ProxyArg>, Arg1: ProxyArg>, - Arg2: ProxyArg>>, >( self, requested_token: Arg0, to: Arg1, - opt_refunding_address: Arg2, ) -> TxTypedCall { self.wrapped_tx .raw_call("unwrapTokenCreateTransaction") .argument(&requested_token) .argument(&to) - .argument(&opt_refunding_address) .original_result() } @@ -234,19 +231,6 @@ where .original_result() } - pub fn set_bridge_proxy_contract_address< - Arg0: ProxyArg>>, - >( - self, - opt_new_address: Arg0, - ) -> TxTypedCall { - self.wrapped_tx - .payment(NotPayable) - .raw_call("setBridgeProxyContractAddress") - .argument(&opt_new_address) - .original_result() - } - pub fn universal_bridged_token_ids( self, ) -> TxTypedCall>> { @@ -304,15 +288,6 @@ where .original_result() } - pub fn bridge_proxy_contract_address( - self, - ) -> TxTypedCall> { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getBridgeProxyContractAddress") - .original_result() - } - pub fn pause_endpoint( self, ) -> TxTypedCall { diff --git a/common/sc-proxies/src/esdt_safe_proxy.rs b/common/sc-proxies/src/esdt_safe_proxy.rs index 6de0d968..b05212a2 100644 --- a/common/sc-proxies/src/esdt_safe_proxy.rs +++ b/common/sc-proxies/src/esdt_safe_proxy.rs @@ -80,18 +80,21 @@ where pub fn upgrade< Arg0: ProxyArg>, Arg1: ProxyArg>, - Arg2: ProxyArg>, + Arg2: ProxyArg>, + Arg3: ProxyArg>, >( self, fee_estimator_contract_address: Arg0, multi_transfer_contract_address: Arg1, - eth_tx_gas_limit: Arg2, + bridge_proxy_contract_address: Arg2, + eth_tx_gas_limit: Arg3, ) -> TxTypedUpgrade { self.wrapped_tx .payment(NotPayable) .raw_upgrade() .argument(&fee_estimator_contract_address) .argument(&multi_transfer_contract_address) + .argument(&bridge_proxy_contract_address) .argument(ð_tx_gas_limit) .original_result() } @@ -152,34 +155,34 @@ where /// fee_amount = price_per_gas_unit * eth_tx_gas_limit pub fn create_transaction< Arg0: ProxyArg>, - Arg1: ProxyArg>>, + Arg1: ProxyArg>>, >( self, to: Arg0, - opt_refund_address: Arg1, + opt_refund_info: Arg1, ) -> TxTypedCall { self.wrapped_tx .raw_call("createTransaction") .argument(&to) - .argument(&opt_refund_address) + .argument(&opt_refund_info) .original_result() } pub fn create_transaction_sc_call< Arg0: ProxyArg>, Arg1: ProxyArg>, - Arg2: ProxyArg>>, + Arg2: ProxyArg>>, >( self, to: Arg0, data: Arg1, - opt_refund_address: Arg2, + opt_refund_info: Arg2, ) -> TxTypedCall { self.wrapped_tx .raw_call("createTransactionSCCall") .argument(&to) .argument(&data) - .argument(&opt_refund_address) + .argument(&opt_refund_info) .original_result() } @@ -212,16 +215,48 @@ where .original_result() } - pub fn withdraw_total_fees_on_ethereum< + pub fn set_bridge_proxy_contract_address< + Arg0: ProxyArg>>, + >( + self, + opt_new_address: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("setBridgeProxyContractAddress") + .argument(&opt_new_address) + .original_result() + } + + pub fn withdraw_refund_fees_for_ethereum< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( + self, + token_id: Arg0, + multisig_owner: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("withdrawRefundFeesForEthereum") + .argument(&token_id) + .argument(&multisig_owner) + .original_result() + } + + pub fn withdraw_transaction_fees< Arg0: ProxyArg>, + Arg1: ProxyArg>, >( self, token_id: Arg0, + multisig_owner: Arg1, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) - .raw_call("withdrawTotalFeesOnEthereum") + .raw_call("withdrawTransactionFees") .argument(&token_id) + .argument(&multisig_owner) .original_result() } @@ -265,6 +300,32 @@ where .original_result() } + pub fn get_refund_fees_for_ethereum< + Arg0: ProxyArg>, + >( + self, + token_id: Arg0, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getRefundFeesForEthereum") + .argument(&token_id) + .original_result() + } + + pub fn get_transaction_fees< + Arg0: ProxyArg>, + >( + self, + token_id: Arg0, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getTransactionFees") + .argument(&token_id) + .original_result() + } + pub fn bridged_tokens_wrapper_address( self, ) -> TxTypedCall> { @@ -274,6 +335,15 @@ where .original_result() } + pub fn bridge_proxy_contract_address( + self, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getBridgeProxyContractAddress") + .original_result() + } + pub fn set_fee_estimator_contract_address< Arg0: ProxyArg>, >( @@ -745,3 +815,14 @@ where .original_result() } } + +#[type_abi] +#[derive(TopEncode, TopDecode, NestedEncode, NestedDecode, Clone, ManagedVecItem, PartialEq)] +pub struct RefundInfo +where + Api: ManagedTypeApi, +{ + pub address: ManagedAddress, + pub initial_batch_id: u64, + pub initial_nonce: u64, +} diff --git a/common/sc-proxies/src/multisig_proxy.rs b/common/sc-proxies/src/multisig_proxy.rs index f73fcb88..a652c8ba 100644 --- a/common/sc-proxies/src/multisig_proxy.rs +++ b/common/sc-proxies/src/multisig_proxy.rs @@ -237,7 +237,7 @@ where .original_result() } - pub fn withdraw_total_fees_on_ethereum< + pub fn withdraw_refund_fees_for_ethereum< Arg0: ProxyArg>, >( self, @@ -245,7 +245,20 @@ where ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) - .raw_call("withdrawTotalFeesOnEthereum") + .raw_call("withdrawRefundFeesForEthereum") + .argument(&token_id) + .original_result() + } + + pub fn withdraw_transaction_fees< + Arg0: ProxyArg>, + >( + self, + token_id: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("withdrawTransactionFees") .argument(&token_id) .original_result() } diff --git a/esdt-safe/src/lib.rs b/esdt-safe/src/lib.rs index bb9477b3..5f2feed1 100644 --- a/esdt-safe/src/lib.rs +++ b/esdt-safe/src/lib.rs @@ -23,7 +23,16 @@ pub struct TransactionDetails { pub actual_bridged_amount: BigUint, pub required_fee: BigUint, pub to_address: ManagedBuffer, - pub caller_address: ManagedBuffer, + pub is_refund_tx: bool, + pub refund_info: RefundInfo +} + +#[type_abi] +#[derive(TopEncode, TopDecode, NestedEncode, NestedDecode, Clone, ManagedVecItem, PartialEq)] +pub struct RefundInfo { + pub address: ManagedAddress, + pub initial_batch_id: u64, + pub initial_nonce: u64 } #[multiversx_sc::contract] @@ -75,12 +84,15 @@ pub trait EsdtSafe: &self, fee_estimator_contract_address: ManagedAddress, multi_transfer_contract_address: ManagedAddress, + bridge_proxy_contract_address: ManagedAddress, eth_tx_gas_limit: BigUint, ) { self.fee_estimator_contract_address() .set(&fee_estimator_contract_address); self.multi_transfer_contract_address() .set(&multi_transfer_contract_address); + self.bridge_proxy_contract_address(). + set(&bridge_proxy_contract_address); self.eth_tx_gas_limit().set(ð_tx_gas_limit); @@ -134,7 +146,7 @@ pub trait EsdtSafe: match tx_status { TransactionStatus::Executed => {} TransactionStatus::Rejected => { - let addr = ManagedAddress::try_from(tx.from).unwrap(); + let addr = ManagedAddress::try_from(tx.from.clone()).unwrap(); self.mark_refund(&addr, &tx.token_identifier, &tx.amount); } _ => { @@ -142,7 +154,15 @@ pub trait EsdtSafe: } } - self.set_status_event(batch_id, tx.nonce, tx_status); + self.set_status_event( + batch_id, + tx.from, + tx.to, + tx.token_identifier, + tx.amount, + tx.nonce, + tx_status, + ); } self.clear_first_batch(&mut tx_batch); @@ -201,7 +221,7 @@ pub trait EsdtSafe: } let actual_bridged_amount = refund_tx.amount - &required_fee; - self.total_fees_on_ethereum(&refund_tx.token_identifier) + self.refund_fees_for_ethereum(&refund_tx.token_identifier) .update(|fees| *fees += required_fee); let tx_nonce = self.get_and_save_next_tx_id(); @@ -225,15 +245,15 @@ pub trait EsdtSafe: let mint_balances_mapper = self.mint_balances(&refund_token_id); if !self.native_token(&refund_token_id).get() { require!( - burn_balances_mapper.get() - <= &mint_balances_mapper.get() - &actual_bridged_amount, - "Not enough burned tokens!" + mint_balances_mapper.get() + >= &burn_balances_mapper.get() + &actual_bridged_amount, + "Not enough minted tokens!" ); } - let mint_executed = self.internal_mint(&refund_token_id, &actual_bridged_amount); - require!(mint_executed, "Cannot do the mint action!"); - mint_balances_mapper.update(|minted| { - *minted += &actual_bridged_amount; + let burn_executed = self.internal_burn(&refund_token_id, &actual_bridged_amount); + require!(burn_executed, "Cannot do the burn action!"); + burn_balances_mapper.update(|burned| { + *burned += &actual_bridged_amount; }); } else { self.total_balances(&refund_token_id).update(|total| { @@ -252,141 +272,164 @@ pub trait EsdtSafe: } fn create_transaction_common( - &self, - to: EthAddress, - opt_refund_address: OptionalValue, - ) -> TransactionDetails { - require!(self.not_paused(), "Cannot create transaction while paused"); - - let (payment_token, payment_amount) = self.call_value().single_fungible_esdt(); - let token_nonce = self.call_value().single_esdt().token_nonce; - require!( - token_nonce == 0, - "Only fungible tokens are accepted for this transaction" - ); - self.require_token_in_whitelist(&payment_token); - - let required_fee = self.calculate_required_fee(&payment_token); - require!( - required_fee < payment_amount, - "Transaction fees cost more than the entire bridged amount" - ); - - self.require_below_max_amount(&payment_token, &payment_amount); + &self, + to: EthAddress, + opt_refund_info: OptionalValue>, + ) -> TransactionDetails { + require!(self.not_paused(), "Cannot create transaction while paused"); - // This addr is used for the refund, if the transaction fails - // This is passed by the BridgeTokenWrapper contract - let mut is_refund_tx = false; - let caller = self.blockchain().get_caller(); - let user_addr = match opt_refund_address { - OptionalValue::Some(addr) => { - require!( - caller == self.bridged_tokens_wrapper_address().get(), - "Wrong caller for a refund tx" - ); - is_refund_tx = true; - addr - } - OptionalValue::None => self.blockchain().get_caller(), - }; + let (payment_token, payment_amount) = self.call_value().single_fungible_esdt(); + self.require_token_in_whitelist(&payment_token); - self.accumulated_transaction_fees(&payment_token) - .update(|fees| *fees += &required_fee); + let required_fee = self.calculate_required_fee(&payment_token); + require!( + required_fee < payment_amount, + "Transaction fees cost more than the entire bridged amount" + ); - let actual_bridged_amount = payment_amount - required_fee.clone(); - let tx_nonce = self.get_and_save_next_tx_id(); - let tx = Transaction { - block_nonce: self.blockchain().get_block_nonce(), - nonce: tx_nonce, - from: user_addr.as_managed_buffer().clone(), - to: to.as_managed_buffer().clone(), - token_identifier: payment_token.clone(), - amount: actual_bridged_amount.clone(), - is_refund_tx, - }; + self.require_below_max_amount(&payment_token, &payment_amount); - let batch_id = self.add_to_batch(tx.clone()); - if self.mint_burn_token(&payment_token).get() { - let burn_balances_mapper = self.burn_balances(&payment_token); - let mint_balances_mapper = self.mint_balances(&payment_token); - if !self.native_token(&payment_token).get() { - require!( - mint_balances_mapper.get() - >= &burn_balances_mapper.get() + &actual_bridged_amount, - "Not enough minted tokens!" - ); + // This addr is used for the refund, if the transaction fails + // This is passed by the BridgeTokenWrapper contract + let mut is_refund_tx = false; + let caller = self.blockchain().get_caller(); + let refund_info = match opt_refund_info { + OptionalValue::Some(refund_info) => { + if caller == self.bridge_proxy_contract_address().get() { + is_refund_tx = true; + refund_info + } else if caller == self.bridged_tokens_wrapper_address().get() { + refund_info + } else { + sc_panic!("Cannot specify a refund address from this caller"); } - let burn_executed = self.internal_burn(&payment_token, &actual_bridged_amount); - require!(burn_executed, "Cannot do the burn action!"); - burn_balances_mapper.update(|burned| { - *burned += &actual_bridged_amount; - }); - } else { - self.total_balances(&payment_token).update(|total| { - *total += &actual_bridged_amount; - }); } - TransactionDetails { - batch_id, - tx_nonce, - payment_token, - actual_bridged_amount, - required_fee, - to_address: to.as_managed_buffer().clone(), - caller_address: user_addr.as_managed_buffer().clone(), + OptionalValue::None => RefundInfo{ address: caller, initial_batch_id: 0, initial_nonce: 0}, + }; + + self.accumulated_transaction_fees(&payment_token) + .update(|fees| *fees += &required_fee); + + let actual_bridged_amount = payment_amount - required_fee.clone(); + let tx_nonce = self.get_and_save_next_tx_id(); + let tx = Transaction { + block_nonce: self.blockchain().get_block_nonce(), + nonce: tx_nonce, + from: refund_info.address.as_managed_buffer().clone(), + to: to.as_managed_buffer().clone(), + token_identifier: payment_token.clone(), + amount: actual_bridged_amount.clone(), + is_refund_tx, + }; + + let batch_id = self.add_to_batch(tx.clone()); + if self.mint_burn_token(&payment_token).get() { + let burn_balances_mapper = self.burn_balances(&payment_token); + let mint_balances_mapper = self.mint_balances(&payment_token); + if !self.native_token(&payment_token).get() { + require!( + mint_balances_mapper.get() + >= &burn_balances_mapper.get() + &actual_bridged_amount, + "Not enough minted tokens!" + ); } + let burn_executed = self.internal_burn(&payment_token, &actual_bridged_amount); + require!(burn_executed, "Cannot do the burn action!"); + burn_balances_mapper.update(|burned| { + *burned += &actual_bridged_amount; + }); + } else { + self.total_balances(&payment_token).update(|total| { + *total += &actual_bridged_amount; + }); + } + TransactionDetails { + batch_id, + tx_nonce, + payment_token, + actual_bridged_amount, + required_fee, + to_address: tx.to, + is_refund_tx, + refund_info } + } + + // endpoints - // endpoints - - /// Create an MultiversX -> Ethereum transaction. Only fungible tokens are accepted. - /// - /// Every transfer will have a part of the tokens subtracted as fees. - /// The fee amount depends on the global eth_tx_gas_limit - /// and the current GWEI price, respective to the bridged token - /// - /// fee_amount = price_per_gas_unit * eth_tx_gas_limit - #[payable("*")] - #[endpoint(createTransaction)] - fn create_transaction( - &self, - to: EthAddress, - opt_refund_address: OptionalValue, - ) { - let transaction_details = self.create_transaction_common(to, opt_refund_address); + /// Create an MultiversX -> Ethereum transaction. Only fungible tokens are accepted. + /// + /// Every transfer will have a part of the tokens subtracted as fees. + /// The fee amount depends on the global eth_tx_gas_limit + /// and the current GWEI price, respective to the bridged token + /// + /// fee_amount = price_per_gas_unit * eth_tx_gas_limit + #[payable("*")] + #[endpoint(createTransaction)] + fn create_transaction( + &self, + to: EthAddress, + opt_refund_info: OptionalValue>, + ) { + let transaction_details = self.create_transaction_common(to, opt_refund_info); + if !transaction_details.is_refund_tx { self.create_transaction_event( transaction_details.batch_id, transaction_details.tx_nonce, transaction_details.payment_token, transaction_details.actual_bridged_amount, transaction_details.required_fee, - transaction_details.to_address, - transaction_details.caller_address, + transaction_details.refund_info.address.as_managed_buffer().clone(), + transaction_details.to_address + ); + } else { + self.create_refund_transaction_event( + transaction_details.batch_id, + transaction_details.tx_nonce, + transaction_details.payment_token, + transaction_details.actual_bridged_amount, + transaction_details.required_fee, + transaction_details.refund_info.initial_batch_id, + transaction_details.refund_info.initial_nonce, ); } + } - #[payable("*")] - #[endpoint(createTransactionSCCall)] - fn create_transaction_sc_call( - &self, - to: EthAddress, - data: ManagedBuffer, - opt_refund_address: OptionalValue, - ) { - let transaction_details = self.create_transaction_common(to, opt_refund_address); + #[payable("*")] + #[endpoint(createTransactionSCCall)] + fn create_transaction_sc_call( + &self, + to: EthAddress, + data: ManagedBuffer, + opt_refund_info: OptionalValue>, + ) { + let transaction_details = self.create_transaction_common(to, opt_refund_info); + if !transaction_details.is_refund_tx { self.create_transaction_sc_call_event( transaction_details.batch_id, transaction_details.tx_nonce, transaction_details.payment_token, transaction_details.actual_bridged_amount, transaction_details.required_fee, + transaction_details.refund_info.address.as_managed_buffer().clone(), transaction_details.to_address, - transaction_details.caller_address, - data, + data + ); + } else { + self.create_refund_transaction_sc_call_event( + transaction_details.batch_id, + transaction_details.tx_nonce, + transaction_details.payment_token, + transaction_details.actual_bridged_amount, + transaction_details.required_fee, + transaction_details.refund_info.initial_batch_id, + transaction_details.refund_info.initial_nonce, + data ); } + } /// Claim funds for failed MultiversX -> Ethereum transactions. /// These are not sent automatically to prevent the contract getting stuck. @@ -430,13 +473,55 @@ pub trait EsdtSafe: } #[only_owner] - #[endpoint(withdrawTotalFeesOnEthereum)] - fn withdraw_total_fees_on_ethereum(&self, token_id: TokenIdentifier) { - let amount_out = self.total_fees_on_ethereum(&token_id).get(); + #[endpoint(setBridgeProxyContractAddress)] + fn set_bridge_proxy_contract_address(&self, opt_new_address: OptionalValue) { + match opt_new_address { + OptionalValue::Some(sc_addr) => { + require!( + self.blockchain().is_smart_contract(&sc_addr), + "Invalid bridge proxy contract address" + ); + + self.bridge_proxy_contract_address().set(&sc_addr); + } + OptionalValue::None => self.bridge_proxy_contract_address().clear(), + } + } + + #[only_owner] + #[endpoint(withdrawRefundFeesForEthereum)] + fn withdraw_refund_fees_for_ethereum( + &self, + token_id: TokenIdentifier, + multisig_owner: ManagedAddress, + ) { + let refund_fees_for_ethereum_mapper = self.refund_fees_for_ethereum(&token_id); + require!( + !refund_fees_for_ethereum_mapper.is_empty(), + "There are no fees to withdraw" + ); + let amount_out = refund_fees_for_ethereum_mapper.get(); self.tx() - .to(ToCaller) + .to(multisig_owner) + .single_esdt(&token_id, 0, &amount_out) + .transfer(); + refund_fees_for_ethereum_mapper.set(BigUint::zero()); + } + + #[only_owner] + #[endpoint(withdrawTransactionFees)] + fn withdraw_transaction_fees(&self, token_id: TokenIdentifier, multisig_owner: ManagedAddress) { + let accumulated_transaction_fees_mapper = self.accumulated_transaction_fees(&token_id); + require!( + !accumulated_transaction_fees_mapper.is_empty(), + "There are no fees to withdraw" + ); + let amount_out = accumulated_transaction_fees_mapper.get(); + self.tx() + .to(multisig_owner) .single_esdt(&token_id, 0, &amount_out) .transfer(); + accumulated_transaction_fees_mapper.set(BigUint::zero()); } #[view(computeTotalAmmountsFromIndex)] @@ -492,8 +577,6 @@ pub trait EsdtSafe: refund_amounts } - // views - #[view(getTotalRefundAmounts)] fn get_total_refund_amounts(&self) -> MultiValueEncoded> { let mut refund_amounts = MultiValueEncoded::new(); @@ -507,6 +590,25 @@ pub trait EsdtSafe: refund_amounts } + #[view(getRefundFeesForEthereum)] + fn get_refund_fees_for_ethereum(&self, token_id: TokenIdentifier) -> BigUint { + let refund_fees_for_ethereum_mapper = self.refund_fees_for_ethereum(&token_id); + if refund_fees_for_ethereum_mapper.is_empty() { + BigUint::zero() + } else { + refund_fees_for_ethereum_mapper.get() + } + } + + #[view(getTransactionFees)] + fn get_transaction_fees(&self, token_id: TokenIdentifier) -> BigUint { + let accumulated_transaction_fees_mapper = self.accumulated_transaction_fees(&token_id); + if accumulated_transaction_fees_mapper.is_empty() { + BigUint::zero() + } else { + accumulated_transaction_fees_mapper.get() + } + } // private fn rebalance_for_refund(&self, token_id: &TokenIdentifier, amount: &BigUint) { @@ -548,6 +650,31 @@ pub trait EsdtSafe: #[indexed] recipient: ManagedBuffer, ); + #[event("createRefundTransactionEvent")] + fn create_refund_transaction_event( + &self, + #[indexed] batch_id: u64, + #[indexed] tx_id: u64, + #[indexed] token_id: TokenIdentifier, + #[indexed] amount: BigUint, + #[indexed] fee: BigUint, + #[indexed] initial_batch_id: u64, + #[indexed] initial_tx_id: u64, + ); + + #[event("createRefundTransactionEvent")] + fn create_refund_transaction_sc_call_event( + &self, + #[indexed] batch_id: u64, + #[indexed] tx_id: u64, + #[indexed] token_id: TokenIdentifier, + #[indexed] amount: BigUint, + #[indexed] fee: BigUint, + #[indexed] initial_batch_id: u64, + #[indexed] initial_tx_id: u64, + #[indexed] data: ManagedBuffer, + ); + #[event("createTransactionScCallEvent")] fn create_transaction_sc_call_event( &self, @@ -580,6 +707,10 @@ pub trait EsdtSafe: fn set_status_event( &self, #[indexed] batch_id: u64, + #[indexed] from: ManagedBuffer, + #[indexed] to: ManagedBuffer, + #[indexed] token_id: TokenIdentifier, + #[indexed] amount: BigUint, #[indexed] tx_id: u64, #[indexed] tx_status: TransactionStatus, ); @@ -589,8 +720,8 @@ pub trait EsdtSafe: #[storage_mapper("totalRefundAmount")] fn total_refund_amount(&self, token_id: &TokenIdentifier) -> SingleValueMapper; - #[storage_mapper("totalFeesOnEthereum")] - fn total_fees_on_ethereum(&self, token_id: &TokenIdentifier) -> SingleValueMapper; + #[storage_mapper("refundFeesForEthereum")] + fn refund_fees_for_ethereum(&self, token_id: &TokenIdentifier) -> SingleValueMapper; #[storage_mapper("refundAmount")] fn refund_amount( @@ -602,4 +733,8 @@ pub trait EsdtSafe: #[view(getBridgedTokensWrapperAddress)] #[storage_mapper("bridgedTokensWrapperAddress")] fn bridged_tokens_wrapper_address(&self) -> SingleValueMapper; + + #[view(getBridgeProxyContractAddress)] + #[storage_mapper("bridgeProxyContractAddress")] + fn bridge_proxy_contract_address(&self) -> SingleValueMapper; } diff --git a/esdt-safe/wasm/src/lib.rs b/esdt-safe/wasm/src/lib.rs index 924c3ef8..3d4f204d 100644 --- a/esdt-safe/wasm/src/lib.rs +++ b/esdt-safe/wasm/src/lib.rs @@ -6,9 +6,9 @@ // Init: 1 // Upgrade: 1 -// Endpoints: 47 +// Endpoints: 52 // Async Callback (empty): 1 -// Total number of exported functions: 50 +// Total number of exported functions: 55 #![no_std] @@ -26,11 +26,16 @@ multiversx_sc_wasm_adapter::endpoints! { createTransactionSCCall => create_transaction_sc_call claimRefund => claim_refund setBridgedTokensWrapperAddress => set_bridged_tokens_wrapper_contract_address - withdrawTotalFeesOnEthereum => withdraw_total_fees_on_ethereum + setBridgeProxyContractAddress => set_bridge_proxy_contract_address + withdrawRefundFeesForEthereum => withdraw_refund_fees_for_ethereum + withdrawTransactionFees => withdraw_transaction_fees computeTotalAmmountsFromIndex => compute_total_amounts_from_index getRefundAmounts => get_refund_amounts getTotalRefundAmounts => get_total_refund_amounts + getRefundFeesForEthereum => get_refund_fees_for_ethereum + getTransactionFees => get_transaction_fees getBridgedTokensWrapperAddress => bridged_tokens_wrapper_address + getBridgeProxyContractAddress => bridge_proxy_contract_address setFeeEstimatorContractAddress => set_fee_estimator_contract_address setEthTxGasLimit => set_eth_tx_gas_limit setDefaultPricePerGasUnit => set_default_price_per_gas_unit diff --git a/multi-transfer-esdt/src/bridge_proxy_contract_proxy.rs b/multi-transfer-esdt/src/bridge_proxy_contract_proxy.rs index 842e5d22..768889b6 100644 --- a/multi-transfer-esdt/src/bridge_proxy_contract_proxy.rs +++ b/multi-transfer-esdt/src/bridge_proxy_contract_proxy.rs @@ -87,13 +87,16 @@ where { pub fn deposit< Arg0: ProxyArg>, + Arg1: ProxyArg, >( self, eth_tx: Arg0, + batch_id: Arg1, ) -> TxTypedCall { self.wrapped_tx .raw_call("deposit") .argument(ð_tx) + .argument(&batch_id) .original_result() } @@ -110,16 +113,12 @@ where .original_result() } - pub fn cancel< - Arg0: ProxyArg, - >( + pub fn update_lowest_tx_id( self, - tx_id: Arg0, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) - .raw_call("cancel") - .argument(&tx_id) + .raw_call("updateLowestTxId") .original_result() } diff --git a/multi-transfer-esdt/src/bridged_tokens_wrapper_proxy.rs b/multi-transfer-esdt/src/bridged_tokens_wrapper_proxy.rs index 852e4057..df5b7a63 100644 --- a/multi-transfer-esdt/src/bridged_tokens_wrapper_proxy.rs +++ b/multi-transfer-esdt/src/bridged_tokens_wrapper_proxy.rs @@ -206,18 +206,15 @@ where pub fn unwrap_token_create_transaction< Arg0: ProxyArg>, Arg1: ProxyArg>, - Arg2: ProxyArg>>, >( self, requested_token: Arg0, to: Arg1, - opt_refunding_address: Arg2, ) -> TxTypedCall { self.wrapped_tx .raw_call("unwrapTokenCreateTransaction") .argument(&requested_token) .argument(&to) - .argument(&opt_refunding_address) .original_result() } @@ -234,19 +231,6 @@ where .original_result() } - pub fn set_bridge_proxy_contract_address< - Arg0: ProxyArg>>, - >( - self, - opt_new_address: Arg0, - ) -> TxTypedCall { - self.wrapped_tx - .payment(NotPayable) - .raw_call("setBridgeProxyContractAddress") - .argument(&opt_new_address) - .original_result() - } - pub fn universal_bridged_token_ids( self, ) -> TxTypedCall>> { @@ -304,15 +288,6 @@ where .original_result() } - pub fn bridge_proxy_contract_address( - self, - ) -> TxTypedCall> { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getBridgeProxyContractAddress") - .original_result() - } - pub fn pause_endpoint( self, ) -> TxTypedCall { diff --git a/multi-transfer-esdt/src/esdt_safe_proxy.rs b/multi-transfer-esdt/src/esdt_safe_proxy.rs index 6de0d968..59e564f3 100644 --- a/multi-transfer-esdt/src/esdt_safe_proxy.rs +++ b/multi-transfer-esdt/src/esdt_safe_proxy.rs @@ -80,18 +80,21 @@ where pub fn upgrade< Arg0: ProxyArg>, Arg1: ProxyArg>, - Arg2: ProxyArg>, + Arg2: ProxyArg>, + Arg3: ProxyArg>, >( self, fee_estimator_contract_address: Arg0, multi_transfer_contract_address: Arg1, - eth_tx_gas_limit: Arg2, + bridge_proxy_contract_address: Arg2, + eth_tx_gas_limit: Arg3, ) -> TxTypedUpgrade { self.wrapped_tx .payment(NotPayable) .raw_upgrade() .argument(&fee_estimator_contract_address) .argument(&multi_transfer_contract_address) + .argument(&bridge_proxy_contract_address) .argument(ð_tx_gas_limit) .original_result() } @@ -152,16 +155,16 @@ where /// fee_amount = price_per_gas_unit * eth_tx_gas_limit pub fn create_transaction< Arg0: ProxyArg>, - Arg1: ProxyArg>>, + Arg1: ProxyArg>>, >( self, to: Arg0, - opt_refund_address: Arg1, + opt_refund_info: Arg1, ) -> TxTypedCall { self.wrapped_tx .raw_call("createTransaction") .argument(&to) - .argument(&opt_refund_address) + .argument(&opt_refund_info) .original_result() } @@ -212,16 +215,48 @@ where .original_result() } - pub fn withdraw_total_fees_on_ethereum< + pub fn set_bridge_proxy_contract_address< + Arg0: ProxyArg>>, + >( + self, + opt_new_address: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("setBridgeProxyContractAddress") + .argument(&opt_new_address) + .original_result() + } + + pub fn withdraw_refund_fees_for_ethereum< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( + self, + token_id: Arg0, + multisig_owner: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("withdrawRefundFeesForEthereum") + .argument(&token_id) + .argument(&multisig_owner) + .original_result() + } + + pub fn withdraw_transaction_fees< Arg0: ProxyArg>, + Arg1: ProxyArg>, >( self, token_id: Arg0, + multisig_owner: Arg1, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) - .raw_call("withdrawTotalFeesOnEthereum") + .raw_call("withdrawTransactionFees") .argument(&token_id) + .argument(&multisig_owner) .original_result() } @@ -265,6 +300,32 @@ where .original_result() } + pub fn get_refund_fees_for_ethereum< + Arg0: ProxyArg>, + >( + self, + token_id: Arg0, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getRefundFeesForEthereum") + .argument(&token_id) + .original_result() + } + + pub fn get_transaction_fees< + Arg0: ProxyArg>, + >( + self, + token_id: Arg0, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getTransactionFees") + .argument(&token_id) + .original_result() + } + pub fn bridged_tokens_wrapper_address( self, ) -> TxTypedCall> { @@ -274,6 +335,15 @@ where .original_result() } + pub fn bridge_proxy_contract_address( + self, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getBridgeProxyContractAddress") + .original_result() + } + pub fn set_fee_estimator_contract_address< Arg0: ProxyArg>, >( @@ -745,3 +815,14 @@ where .original_result() } } + +#[type_abi] +#[derive(TopEncode, TopDecode, NestedEncode, NestedDecode, Clone, ManagedVecItem, PartialEq)] +pub struct RefundInfo +where + Api: ManagedTypeApi, +{ + pub address: ManagedAddress, + pub initial_batch_id: u64, + pub initial_nonce: u64, +} diff --git a/multi-transfer-esdt/src/lib.rs b/multi-transfer-esdt/src/lib.rs index 9c4715f6..37afc4e0 100644 --- a/multi-transfer-esdt/src/lib.rs +++ b/multi-transfer-esdt/src/lib.rs @@ -99,7 +99,7 @@ pub trait MultiTransferEsdt: } let payments_after_wrapping = self.wrap_tokens(valid_payments_list); - self.distribute_payments(valid_tx_list, payments_after_wrapping); + self.distribute_payments(valid_tx_list, payments_after_wrapping, batch_id); self.add_multiple_tx_to_batch(&refund_tx_list); } @@ -284,6 +284,7 @@ pub trait MultiTransferEsdt: &self, transfers: ManagedVec>, payments: PaymentsVec, + batch_id: u64, ) { let bridge_proxy_addr = self.bridge_proxy_contract_address().get(); for (eth_tx, p) in transfers.iter().zip(payments.iter()) { @@ -291,7 +292,7 @@ pub trait MultiTransferEsdt: self.tx() .to(bridge_proxy_addr.clone()) .typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy) - .deposit(ð_tx) + .deposit(ð_tx, batch_id) .single_esdt(&p.token_identifier, 0, &p.amount) .sync_call(); } else { diff --git a/multi-transfer-esdt/tests/multi_transfer_blackbox_test.rs b/multi-transfer-esdt/tests/multi_transfer_blackbox_test.rs index 98308181..8a8bf5d2 100644 --- a/multi-transfer-esdt/tests/multi_transfer_blackbox_test.rs +++ b/multi-transfer-esdt/tests/multi_transfer_blackbox_test.rs @@ -2,7 +2,7 @@ use bridge_proxy::{config::ProxyTrait as _, ProxyTrait as _}; use bridged_tokens_wrapper::ProxyTrait as _; -use esdt_safe::{EsdtSafe, ProxyTrait as _}; +use esdt_safe::{EsdtSafe, ProxyTrait as _, RefundInfo}; use esdt_safe_proxy::EsdtSafeProxyMethods; use multi_transfer_esdt::*; @@ -173,6 +173,7 @@ impl MultiTransferTestState { .upgrade( ManagedAddress::zero(), MULTI_TRANSFER_ADDRESS.to_address(), + BRIDGE_PROXY_ADDRESS.to_address(), ESDT_SAFE_ETH_TX_GAS_LIMIT, ) .code(ESDT_SAFE_CODE_PATH) @@ -294,8 +295,8 @@ impl MultiTransferTestState { self.world .tx() .from(OWNER_ADDRESS) - .to(BRIDGED_TOKENS_WRAPPER_ADDRESS) - .typed(bridged_tokens_wrapper_proxy::BridgedTokensWrapperProxy) + .to(ESDT_SAFE_ADDRESS) + .typed(esdt_safe_proxy::EsdtSafeProxy) .set_bridge_proxy_contract_address(OptionalValue::Some( BRIDGE_PROXY_ADDRESS.to_address(), )) @@ -506,9 +507,8 @@ impl MultiTransferTestState { amount: u64, expected_error: &str, ) { - let none_addr: OptionalValue> = OptionalValue::None; self.esdt_raw_transaction() - .create_transaction(EthAddress::zero(), none_addr) + .create_transaction(EthAddress::zero(),OptionalValue::None::>) .egld_or_single_esdt( &EgldOrEsdtTokenIdentifier::esdt(token_id), 0, @@ -519,9 +519,8 @@ impl MultiTransferTestState { } fn single_transaction_should_work(&mut self, token_id: TestTokenIdentifier, amount: u64) { - let none_addr: OptionalValue> = OptionalValue::None; self.esdt_raw_transaction() - .create_transaction(EthAddress::zero(), none_addr) + .create_transaction(EthAddress::zero(), OptionalValue::None::>) .egld_or_single_esdt( &EgldOrEsdtTokenIdentifier::esdt(token_id), 0, @@ -1321,7 +1320,6 @@ fn test_unwrap_token_create_transaction_paused() { .unwrap_token_create_transaction( TokenIdentifier::from(UNIVERSAL_TOKEN_IDENTIFIER), EthAddress::zero(), - OptionalValue::Some(ManagedAddress::zero()), ) .egld_or_single_esdt( &EgldOrEsdtTokenIdentifier::esdt(UNIVERSAL_TOKEN_IDENTIFIER), @@ -1375,7 +1373,6 @@ fn test_unwrap_token_create_transaction_insufficient_liquidity() { .unwrap_token_create_transaction( WRAPPED_TOKEN_ID, EthAddress::zero(), - OptionalValue::Some(ManagedAddress::zero()), ) .egld_or_single_esdt( &EgldOrEsdtTokenIdentifier::esdt(UNIVERSAL_TOKEN_IDENTIFIER), @@ -1403,7 +1400,6 @@ fn test_unwrap_token_create_transaction_should_work() { .unwrap_token_create_transaction( TokenIdentifier::from(WRAPPED_TOKEN_ID), EthAddress::zero(), - OptionalValue::Some(ManagedAddress::zero()), ) .egld_or_single_esdt( &EgldOrEsdtTokenIdentifier::esdt(WRAPPED_TOKEN_ID), @@ -1430,7 +1426,6 @@ fn test_unwrap_token_create_transaction_amount_zero() { .unwrap_token_create_transaction( TokenIdentifier::from(WRAPPED_TOKEN_ID), EthAddress::zero(), - OptionalValue::Some(ManagedAddress::zero()), ) .egld_or_single_esdt( &EgldOrEsdtTokenIdentifier::esdt(UNIVERSAL_TOKEN_IDENTIFIER), diff --git a/multisig/interaction/config/aggregator-snippets.sh b/multisig/interaction/config/aggregator-snippets.sh index b2c1a5a1..a4422815 100644 --- a/multisig/interaction/config/aggregator-snippets.sh +++ b/multisig/interaction/config/aggregator-snippets.sh @@ -1,9 +1,10 @@ deployAggregator() { - CHECK_VARIABLES AGGREGATOR_WASM CHAIN_SPECIFIC_TOKEN ALICE_ADDRESS + CHECK_VARIABLES AGGREGATOR_WASM CHAIN_SPECIFIC_TOKEN ORACLE_ADDR_0 ORACLE_ADDR_1 ORACLE_ADDR_2 - MIN_STAKE=$(echo "$RELAYER_REQUIRED_STAKE*10^18" | bc) + STAKE=$(echo "$ORACLE_REQUIRED_STAKE*10^18" | bc) mxpy --verbose contract deploy --bytecode=${AGGREGATOR_WASM} --recall-nonce --pem=${ALICE} \ - --gas-limit=100000000 --arguments str:EGLD ${MIN_STAKE} 1 1 1 ${ALICE_ADDRESS} \ + --gas-limit=100000000 --arguments str:EGLD ${STAKE} 1 2 3 \ + ${ORACLE_ADDR_0} ${ORACLE_ADDR_1} ${ORACLE_ADDR_2} \ --send --outfile=deploy-price-agregator-testnet.interaction.json --proxy=${PROXY} --chain=${CHAIN_ID} || return TRANSACTION=$(mxpy data parse --file="./deploy-price-agregator-testnet.interaction.json" --expression="data['emittedTransactionHash']") @@ -17,13 +18,25 @@ deployAggregator() { update-config AGGREGATOR ${ADDRESS} } -stake() { +stakeOracles() { CHECK_VARIABLES AGGREGATOR - MIN_STAKE=$(echo "$RELAYER_REQUIRED_STAKE*10^18" | bc) - mxpy --verbose contract call ${AGGREGATOR} --recall-nonce --pem=${ALICE} \ - --gas-limit=35000000 --function="stake" --value=${MIN_STAKE} \ + STAKE=$(echo "$ORACLE_REQUIRED_STAKE*10^18" | bc) + echo "---------------------------------------------------------" + mxpy --verbose contract call ${AGGREGATOR} --recall-nonce --pem=${ORACLE_WALLET0} \ + --gas-limit=35000000 --function="stake" --value=${STAKE} \ + --send --proxy=${PROXY} --chain=${CHAIN_ID} + echo "---------------------------------------------------------" + echo "---------------------------------------------------------" + mxpy --verbose contract call ${AGGREGATOR} --recall-nonce --pem=${ORACLE_WALLET1} \ + --gas-limit=35000000 --function="stake" --value=${STAKE} \ + --send --proxy=${PROXY} --chain=${CHAIN_ID} + echo "---------------------------------------------------------" + echo "---------------------------------------------------------" + mxpy --verbose contract call ${AGGREGATOR} --recall-nonce --pem=${ORACLE_WALLET2} \ + --gas-limit=35000000 --function="stake" --value=${STAKE} \ --send --proxy=${PROXY} --chain=${CHAIN_ID} + echo "---------------------------------------------------------" } submitAggregatorBatch() { @@ -32,7 +45,19 @@ submitAggregatorBatch() { FEE=$(echo "scale=0; $FEE_AMOUNT*10^$NR_DECIMALS_CHAIN_SPECIFIC/1" | bc) CURRENT_TIME=$(date +%s) - mxpy --verbose contract call ${AGGREGATOR} --recall-nonce --pem=${ALICE} \ + mxpy --verbose contract call ${AGGREGATOR} --recall-nonce --pem=${ORACLE_WALLET0} \ + --gas-limit=15000000 --function="submitBatch" \ + --arguments str:GWEI str:${CHAIN_SPECIFIC_TOKEN_TICKER} ${CURRENT_TIME} ${FEE} 0 \ + --send --proxy=${PROXY} --chain=${CHAIN_ID} || return + + CURRENT_TIME=$(date +%s) + mxpy --verbose contract call ${AGGREGATOR} --recall-nonce --pem=${ORACLE_WALLET1} \ + --gas-limit=15000000 --function="submitBatch" \ + --arguments str:GWEI str:${CHAIN_SPECIFIC_TOKEN_TICKER} ${CURRENT_TIME} ${FEE} 0 \ + --send --proxy=${PROXY} --chain=${CHAIN_ID} || return + + CURRENT_TIME=$(date +%s) + mxpy --verbose contract call ${AGGREGATOR} --recall-nonce --pem=${ORACLE_WALLET2} \ --gas-limit=15000000 --function="submitBatch" \ --arguments str:GWEI str:${CHAIN_SPECIFIC_TOKEN_TICKER} ${CURRENT_TIME} ${FEE} 0 \ --send --proxy=${PROXY} --chain=${CHAIN_ID} || return @@ -62,3 +87,11 @@ unpauseAggregator() { --gas-limit=5000000 --function="unpause" \ --send --proxy=${PROXY} --chain=${CHAIN_ID} || return } + +aggregator-upgrade() { + CHECK_VARIABLES AGGREGATOR AGGREGATOR_WASM + + mxpy --verbose contract upgrade ${AGGREGATOR} --bytecode=${AGGREGATOR_WASM} --recall-nonce --pem=${ALICE} \ + --gas-limit=100000000 --send \ + --outfile="upgrade-aggregator.json" --proxy=${PROXY} --chain=${CHAIN_ID} || return +} diff --git a/multisig/interaction/config/configs.cfg b/multisig/interaction/config/configs.cfg index 56ebaf71..831f8b34 100644 --- a/multisig/interaction/config/configs.cfg +++ b/multisig/interaction/config/configs.cfg @@ -12,12 +12,14 @@ ALICE_ADDRESS=erd1zsha9cvx7gwraytgp740dcjzwy9v5xwnmas77d33uve6sk0rs0vqel4ln5 #============WASM FILES============== -AGGREGATOR_WASM="./price-aggregator.wasm" +AGGREGATOR_WASM="./multiversx-price-aggregator-sc.wasm" SAFE_WASM="./esdt-safe.wasm" BRIDGED_TOKENS_WRAPPER_WASM="./bridged-tokens-wrapper.wasm" MULTI_TRANSFER_WASM="./multi-transfer-esdt.wasm" MULTISIG_WASM="./multisig.wasm" PROXY_WASM="./bridge-proxy.wasm" +FAUCET_WASM="./faucet.wasm" +TEST_CALLER_WASM="./test-caller.wasm" #============CONTRACT ADDRESSES============== @@ -26,6 +28,9 @@ SAFE=erd1qqqqqqqqqqqqqpgqkhx64czgpc84eftg6q25lrfyv95ndwtcs0vqwusfuh BRIDGED_TOKENS_WRAPPER=erd1qqqqqqqqqqqqqpgqlgjwk8mpfycxpdf9q2sgzcndtdhdxr5ss0vqgygjmn MULTI_TRANSFER=erd1qqqqqqqqqqqqqpgqjsh8kss3w67xks7ths5d795q3nz8y52as0vqu0ujzg MULTISIG=erd1qqqqqqqqqqqqqpgqdcat402y6c62hv07gt04rynjg4668z9fs0vq3qxepp +BRIDGE_PROXY=erd1qqqqqqqqqqqqqpgqk09rka2dslnf9ns5eze2s5xw2hfjxm0jzlsqzyjh28 +FAUCET=erd1qqqqqqqqqqqqqpgqhhlx9mpdc92l0psszy3cf9lxhg9vzhs8zlsqjeeqqn +TEST_CALLER=erd1qqqqqqqqqqqqqpgq398fy44g59se3pkmjz8tya39pz5q4tuvpqqqgwffes #============TOKENS SETTINGS============== NR_DECIMALS_CHAIN_SPECIFIC=6 @@ -36,7 +41,7 @@ UNIVERSAL_TOKEN_DISPLAY_NAME=WrappedUSDC CHAIN_SPECIFIC_TOKEN_TICKER=ETHUSDC CHAIN_SPECIFIC_TOKEN_DISPLAY_NAME=EthereumWrappedUSDC -UNIVERSAL_TOKENS_ALREADY_MINTED=0 +UNIVERSAL_TOKENS_ALREADY_MINTED=0 # do not add the decimals on this value #============TOKENS TO BE WHITELISTED============== UNIVERSAL_TOKEN= @@ -44,6 +49,10 @@ CHAIN_SPECIFIC_TOKEN=MEX-a659d0 ERC20_TOKEN=0x2E8e0BBe20Ecd819c721D164fb91F7c33BDFC756 MINTBURN_WHITELIST=true NATIVE_TOKEN=true + +TOTAL_BALANCE=0 +MINT_BALANCE=0 +BURN_BALANCE=0 #============BRIDGE SETTINGS============== FEE_AMOUNT=50 # value without decimals @@ -52,21 +61,22 @@ MAX_AMOUNT=100000 # value without decimals RELAYER_REQUIRED_STAKE=0 #1000eGLD SLASH_AMOUNT=0 QUORUM=3 +ORACLE_REQUIRED_STAKE=1 #1EGLD MAX_TX_PER_BATCH=70 MAX_TX_BLOCK_DURATION_PER_BATCH=100 #10minutes #============RELAYERS ADDRESSES============== -RELAYER_ADDR_0=erd1l9hpewk3dd6mz5j0yytjnzqtydukslmsms2d0fn0pg8pc42chqgqk8pm5u -RELAYER_ADDR_1=erd1tfj6fpr5hd5fw8h6efycw42mk3c4wynausntvg6x98kcyn5npkkqmq7t9g -RELAYER_ADDR_2=erd1689ky73s93aptw8ek0wrrzujtus365ygrqgj0hgj4cn09n5k3kuqyhr0j7 -RELAYER_ADDR_3=erd1uae36y2qvrslexcv3mwjqy9lwrlspvkdyjsar2xcj5ctrq7th26q8twvyc -RELAYER_ADDR_4=erd1pkwhtl85ze02ckaf0t6qgycgx863kxyefxyqxumcth0nwtu3a9yqzg2yn2 -RELAYER_ADDR_5=erd197rmyux8ttzuwssh9thsewlzsc766tvpnussqkpew5vm9x63k0kqw56hr7 -RELAYER_ADDR_6=erd1yhqfhsf237uyz4uzzg0duy9hhg8t3j4wtt020c5cy59w2v2jvkgq6nxf0c -RELAYER_ADDR_7=erd1pgvt06tyhlwegkdkzknyhcxfl3wz69wseqeqashm3d83mxjaewzqnug90w -RELAYER_ADDR_8=erd1ujfl0yxff6ey008ef89au4dn486dj549kpjuuu4xxtn9q550x3gqcu6wed -RELAYER_ADDR_9=erd1zsha9cvx7gwraytgp740dcjzwy9v5xwnmas77d33uve6sk0rs0vqel4ln5 +RELAYER_ADDR_0=erd1l9hpewk3dd6mz5j0yytjnzqtydukslmsms2d0fn0pg8pc42chqgqk8pm5u +RELAYER_ADDR_1=erd1tfj6fpr5hd5fw8h6efycw42mk3c4wynausntvg6x98kcyn5npkkqmq7t9g +RELAYER_ADDR_2=erd1689ky73s93aptw8ek0wrrzujtus365ygrqgj0hgj4cn09n5k3kuqyhr0j7 +RELAYER_ADDR_3=erd1uae36y2qvrslexcv3mwjqy9lwrlspvkdyjsar2xcj5ctrq7th26q8twvyc +RELAYER_ADDR_4=erd1pkwhtl85ze02ckaf0t6qgycgx863kxyefxyqxumcth0nwtu3a9yqzg2yn2 +RELAYER_ADDR_5=erd197rmyux8ttzuwssh9thsewlzsc766tvpnussqkpew5vm9x63k0kqw56hr7 +RELAYER_ADDR_6=erd1yhqfhsf237uyz4uzzg0duy9hhg8t3j4wtt020c5cy59w2v2jvkgq6nxf0c +RELAYER_ADDR_7=erd1pgvt06tyhlwegkdkzknyhcxfl3wz69wseqeqashm3d83mxjaewzqnug90w +RELAYER_ADDR_8=erd1ujfl0yxff6ey008ef89au4dn486dj549kpjuuu4xxtn9q550x3gqcu6wed +RELAYER_ADDR_9=erd1zsha9cvx7gwraytgp740dcjzwy9v5xwnmas77d33uve6sk0rs0vqel4ln5 RELAYER_WALLET0="./walletsRelay/${RELAYER_ADDR_0}.pem" RELAYER_WALLET1="./walletsRelay/${RELAYER_ADDR_1}.pem" @@ -79,3 +89,11 @@ RELAYER_WALLET7="./walletsRelay/${RELAYER_ADDR_7}.pem" RELAYER_WALLET8="./walletsRelay/${RELAYER_ADDR_8}.pem" RELAYER_WALLET9="./walletsRelay/${RELAYER_ADDR_9}.pem" +#============ORACLE ADDRESSES============== +ORACLE_ADDR_0=erd1ek7r87m623y94n8htdjhmhwud6vwhxanwl2xzdfl3kccejhefuqqhwjmv2 +ORACLE_ADDR_1=erd1vpz5mpsttd9q5puuaqr7kxfjhwsv2zqqu9jdhyrvkpyfhpnsf5qqhtkkca +ORACLE_ADDR_2=erd10f8xflx9svsje0v2ujggp76jkzyxwpj0rxzgmvx5kle5vqk4f5qqg57m7t + +ORACLE_WALLET0="./walletsOracle/${ORACLE_ADDR_0}.pem" +ORACLE_WALLET1="./walletsOracle/${ORACLE_ADDR_1}.pem" +ORACLE_WALLET2="./walletsOracle/${ORACLE_ADDR_2}.pem" diff --git a/multisig/interaction/config/menu_functions.cfg b/multisig/interaction/config/menu_functions.cfg index d64fb8f1..48c727c5 100644 --- a/multisig/interaction/config/menu_functions.cfg +++ b/multisig/interaction/config/menu_functions.cfg @@ -7,16 +7,12 @@ source $SCRIPTPATH/config/multisig-snippets.sh source $SCRIPTPATH/config/multitransfer-snippets.sh source $SCRIPTPATH/config/proxy-snippets.sh source $SCRIPTPATH/config/relayers-snippets.sh -source $SCRIPTPATH/config/upgrade-snippets.sh source $SCRIPTPATH/config/wrapped-snippets.sh source $SCRIPTPATH/config/safe-snippets.sh +source $SCRIPTPATH/config/testing.sh CHECK_VARIABLES ALICE PROXY CHAIN_ID -function upgrade-wrapper { - wrapper-upgrade -} - function upgrade-wrapper-universal-token { wrapper-updateWrappedToken } @@ -25,23 +21,45 @@ function upgrade-wrapper-chain-specific-token { wrapper-updateWhitelistedToken } +function init-supply-mint-burn { + initSupplyMintBurn +} + function deploy-bridge-contracts { confirmation-with-skip deployAggregator - confirmation-with-skip stake + confirmation-with-skip manual-update-config-file + confirmation-with-skip stakeOracles + confirmation-with-skip deployBridgedTokensWrapper + manual-update-config-file confirmation-with-skip deployMultiTransfer + manual-update-config-file confirmation-with-skip deploySafe - confirmation-with-skip deployMultisig + manual-update-config-file confirmation-with-skip deployBridgeProxy - confirmation-with-skip setBridgeProxyContractAddress - confirmation-with-skip setBridgedTokensWrapper + manual-update-config-file + confirmation-with-skip deployMultisig + manual-update-config-file + + confirmation-with-skip setBridgeProxyContractAddressOnMultiTransfer + confirmation-with-skip setBridgedTokensWrapperOnMultiTransfer + + confirmation-with-skip setBridgedTokensWrapperOnSCProxy + confirmation-with-skip setMultiTransferOnSCProxy + confirmation-with-skip setEsdtSafeOnSCProxy + confirmation-with-skip setEsdtSafeOnWrapper - confirmation-with-skip setWrappingContractAddress + + confirmation-with-skip setBridgedTokensWrapperOnEsdtSafe + confirmation-with-skip setSCProxyOnEsdtSafe + confirmation-with-skip changeChildContractsOwnershipSafe confirmation-with-skip changeChildContractsOwnershipMultiTransfer confirmation-with-skip changeChildContractsOwnershipProxy - confirmation-with-skip setMultiTransferOnEsdtSafe - confirmation-with-skip setEsdtSafeOnMultiTransfer + + confirmation-with-skip setEsdtSafeOnMultiTransferThroughMultisig + + confirmation-with-skip stakeRelayers } function remove-whitelist-token { @@ -86,6 +104,7 @@ function whitelist-token { echo -e confirmation-with-skip manual-update-config-file + confirmation-with-skip setPairDecimals confirmation-with-skip submitAggregatorBatch confirmation-with-skip esdtSafeSetMaxBridgedAmountForToken @@ -101,6 +120,7 @@ function whitelist-native-token { echo -e confirmation-with-skip manual-update-config-file + confirmation-with-skip setPairDecimals confirmation-with-skip submitAggregatorBatch confirmation-with-skip esdtSafeSetMaxBridgedAmountForToken @@ -151,4 +171,47 @@ function mint-chain-specific { update-config UNIVERSAL_TOKENS_ALREADY_MINTED ${AMOUNT_TO_MINT} confirmation-with-skip transferToSC confirmation-with-skip unSetMintRole -} \ No newline at end of file +} + +function upgrade-aggregator { + aggregator-upgrade +} + +function upgrade-wrapper { + wrapper-upgrade +} + +function upgrade-safe { + confirmation-with-skip deploySafeForUpgrade + confirmation-with-skip upgradeSafeContract +} + +function upgrade-multi-transfer { + confirmation-with-skip deployMultiTransferForUpgrade + confirmation-with-skip upgradeMultiTransferContract +} + +function upgrade-proxy { + confirmation-with-skip deployBridgeProxyForUpgrade + confirmation-with-skip upgradeBridgeProxyContract +} + +function upgrade-multisig { + confirmation-with-skip upgradeMultisig +} + +function faucet-deposit { + confirmation-with-skip deployFaucet + echo -e + echo "Update UNIVERSAL_TOKEN and NR_DECIMALS_UNIVERSAL in BRIDGE SETTINGS section in configs.cfg" + echo -e + confirmation-with-skip manual-update-config-file + + confirmation-with-skip setMintRoleForUniversalToken + confirmation-with-skip mintAndDeposit + confirmation-with-skip unSetMintRoleForUniversalToken +} + +function deploy-test-caller { + confirmation-with-skip deployTestCaller +} diff --git a/multisig/interaction/config/multisig-snippets.sh b/multisig/interaction/config/multisig-snippets.sh index e61f8034..a0dade83 100644 --- a/multisig/interaction/config/multisig-snippets.sh +++ b/multisig/interaction/config/multisig-snippets.sh @@ -70,10 +70,14 @@ addMapping() { addTokenToWhitelist() { CHECK_VARIABLES CHAIN_SPECIFIC_TOKEN CHAIN_SPECIFIC_TOKEN_TICKER MULTISIG MINTBURN_WHITELIST NATIVE_TOKEN + BALANCE=$(echo "$TOTAL_BALANCE*10^$NR_DECIMALS_CHAIN_SPECIFIC" | bc) + MINT=$(echo "$MINT_BALANCE*10^$NR_DECIMALS_CHAIN_SPECIFIC" | bc) + BURN=$(echo "$BURN_BALANCE*10^$NR_DECIMALS_CHAIN_SPECIFIC" | bc) + mxpy --verbose contract call ${MULTISIG} --recall-nonce --pem=${ALICE} \ --gas-limit=60000000 --function="esdtSafeAddTokenToWhitelist" \ --arguments str:${CHAIN_SPECIFIC_TOKEN} str:${CHAIN_SPECIFIC_TOKEN_TICKER} ${MINTBURN_WHITELIST} ${NATIVE_TOKEN} \ - --send --proxy=${PROXY} --chain=${CHAIN_ID} + ${BALANCE} ${MINT} ${BURN} --send --proxy=${PROXY} --chain=${CHAIN_ID} } removeTokenFromWhitelist() { @@ -190,7 +194,7 @@ multiTransferEsdtSetMaxBridgedAmountForToken() { } -setMultiTransferOnEsdtSafe() { +setMultiTransferOnEsdtSafeThroughMultisig() { CHECK_VARIABLES MULTISIG mxpy --verbose contract call ${MULTISIG} --recall-nonce --pem=${ALICE} \ @@ -198,10 +202,44 @@ setMultiTransferOnEsdtSafe() { --send --proxy=${PROXY} --chain=${CHAIN_ID} } -setEsdtSafeOnMultiTransfer() { +setEsdtSafeOnMultiTransferThroughMultisig() { CHECK_VARIABLES MULTISIG mxpy --verbose contract call ${MULTISIG} --recall-nonce --pem=${ALICE} \ --gas-limit=60000000 --function="setEsdtSafeOnMultiTransfer" \ --send --proxy=${PROXY} --chain=${CHAIN_ID} -} \ No newline at end of file +} + +initSupplyMintBurn() { + CHECK_VARIABLES MULTISIG + + echo -e + echo "PREREQUIREMENTS: The MINT_BALANCE & BURN_BALANCE values should be defined in configs.cfg file" + echo "The script automatically apply denomination factors based on the number of the decimals the token has" + echo -e + + confirmation-with-skip manual-update-config-file + + MINT=$(echo "$MINT_BALANCE*10^$NR_DECIMALS_CHAIN_SPECIFIC" | bc) + BURN=$(echo "$BURN_BALANCE*10^$NR_DECIMALS_CHAIN_SPECIFIC" | bc) + + mxpy --verbose contract call ${MULTISIG} --recall-nonce --pem=${ALICE} \ + --gas-limit=60000000 --function="initSupplyMintBurnEsdtSafe" \ + --arguments str:${CHAIN_SPECIFIC_TOKEN} ${MINT} ${BURN} \ + --send --proxy=${PROXY} --chain=${CHAIN_ID} +} + +upgradeMultisig() { + CHECK_VARIABLES SAFE MULTI_TRANSFER BRIDGE_PROXY MULTISIG_WASM + + mxpy --verbose contract upgrade ${MULTISIG} --bytecode=${MULTISIG_WASM} --recall-nonce --pem=${ALICE} \ + --gas-limit=100000000 --send \ + --arguments ${SAFE} ${MULTI_TRANSFER} ${BRIDGE_PROXY} \ + --outfile="upgrade-multisig-child-sc.json" --proxy=${PROXY} --chain=${CHAIN_ID} || return + + TRANSACTION=$(mxpy data parse --file="./upgrade-multisig-child-sc.json" --expression="data['emitted_tx']['hash']") + ADDRESS=$(mxpy data parse --file="./upgrade-multisig-child-sc.json" --expression="data['contractAddress']") + + echo "" + echo "Multisig contract updated: ${ADDRESS}" +} diff --git a/multisig/interaction/config/multitransfer-snippets.sh b/multisig/interaction/config/multitransfer-snippets.sh index 72a5a8cc..68958542 100644 --- a/multisig/interaction/config/multitransfer-snippets.sh +++ b/multisig/interaction/config/multitransfer-snippets.sh @@ -13,7 +13,7 @@ deployMultiTransfer() { update-config MULTI_TRANSFER ${ADDRESS} } -setBridgeProxyContractAddress() { +setBridgeProxyContractAddressOnMultiTransfer() { CHECK_VARIABLES MULTI_TRANSFER BRIDGE_PROXY mxpy --verbose contract call ${MULTI_TRANSFER} --recall-nonce --pem=${ALICE} \ @@ -22,11 +22,34 @@ setBridgeProxyContractAddress() { --send --proxy=${PROXY} --chain=${CHAIN_ID} } -setWrappingContractAddress() { +setBridgedTokensWrapperOnMultiTransfer() { CHECK_VARIABLES MULTI_TRANSFER BRIDGED_TOKENS_WRAPPER mxpy --verbose contract call ${MULTI_TRANSFER} --recall-nonce --pem=${ALICE} \ --gas-limit=60000000 --function="setWrappingContractAddress" \ --arguments ${BRIDGED_TOKENS_WRAPPER} \ --send --proxy=${PROXY} --chain=${CHAIN_ID} -} \ No newline at end of file +} + +deployMultiTransferForUpgrade() { + CHECK_VARIABLES MULTI_TRANSFER_WASM + + mxpy --verbose contract deploy --bytecode=${MULTI_TRANSFER_WASM} --recall-nonce --pem=${ALICE} \ + --gas-limit=100000000 --metadata-payable \ + --send --outfile="deploy-multitransfer-upgrade.interaction.json" --proxy=${PROXY} --chain=${CHAIN_ID} || return + + TRANSACTION=$(mxpy data parse --file="./deploy-multitransfer-upgrade.interaction.json" --expression="data['emittedTransactionHash']") + ADDRESS=$(mxpy data parse --file="./deploy-multitransfer-upgrade.interaction.json" --expression="data['contractAddress']") + + echo "" + echo "New multi transfer contract address: ${ADDRESS}" +} + +upgradeMultiTransferContract() { + local NEW_MULTI_TRANSFER_ADDR=$(mxpy data parse --file="./deploy-multitransfer-upgrade.interaction.json" --expression="data['contractAddress']") + + mxpy --verbose contract call ${MULTISIG} --recall-nonce --pem=${ALICE} \ + --gas-limit=400000000 --function="upgradeChildContractFromSource" \ + --arguments ${MULTI_TRANSFER} ${NEW_MULTI_TRANSFER_ADDR} 0x00 \ + --send --outfile="upgrade-multitransfer-child-sc.json" --proxy=${PROXY} --chain=${CHAIN_ID} +} diff --git a/multisig/interaction/config/proxy-snippets.sh b/multisig/interaction/config/proxy-snippets.sh index 51b4fd24..507815d0 100644 --- a/multisig/interaction/config/proxy-snippets.sh +++ b/multisig/interaction/config/proxy-snippets.sh @@ -17,11 +17,53 @@ deployBridgeProxy() { update-config BRIDGE_PROXY ${ADDRESS} } -setBridgedTokensWrapper() { +setBridgedTokensWrapperOnSCProxy() { CHECK_VARIABLES BRIDGE_PROXY BRIDGED_TOKENS_WRAPPER mxpy --verbose contract call ${BRIDGE_PROXY} --recall-nonce --pem=${ALICE} \ - --gas-limit=60000000 --function="setBridgedTokensWrapper" \ + --gas-limit=60000000 --function="setBridgedTokensWrapperAddress" \ --arguments ${BRIDGED_TOKENS_WRAPPER} \ --send --proxy=${PROXY} --chain=${CHAIN_ID} } + +setMultiTransferOnSCProxy() { + CHECK_VARIABLES BRIDGE_PROXY MULTI_TRANSFER + + mxpy --verbose contract call ${BRIDGE_PROXY} --recall-nonce --pem=${ALICE} \ + --gas-limit=60000000 --function="setMultiTransferAddress" \ + --arguments ${MULTI_TRANSFER} \ + --send --proxy=${PROXY} --chain=${CHAIN_ID} +} + +setEsdtSafeOnSCProxy() { + CHECK_VARIABLES BRIDGE_PROXY SAFE + + mxpy --verbose contract call ${BRIDGE_PROXY} --recall-nonce --pem=${ALICE} \ + --gas-limit=60000000 --function="setEsdtSafeAddress" \ + --arguments ${SAFE} \ + --send --proxy=${PROXY} --chain=${CHAIN_ID} +} + +deployBridgeProxyForUpgrade() { + CHECK_VARIABLES PROXY_WASM MULTI_TRANSFER + + mxpy --verbose contract deploy --bytecode=${PROXY_WASM} --recall-nonce --pem=${ALICE} \ + --gas-limit=200000000 \ + --arguments ${MULTI_TRANSFER} \ + --send --outfile="deploy-proxy-upgrade.interaction.json" --proxy=${PROXY} --chain=${CHAIN_ID} || return + + TRANSACTION=$(mxpy data parse --file="./deploy-proxy-upgrade.interaction.json" --expression="data['emittedTransactionHash']") + ADDRESS=$(mxpy data parse --file="./deploy-proxy-upgrade.interaction.json" --expression="data['contractAddress']") + + echo "" + echo "New proxy contract address: ${ADDRESS}" +} + +upgradeBridgeProxyContract() { + local NEW_BRIDGE_PROXY_ADDR=$(mxpy data parse --file="./deploy-proxy-upgrade.interaction.json" --expression="data['contractAddress']") + + mxpy --verbose contract call ${MULTISIG} --recall-nonce --pem=${ALICE} \ + --gas-limit=400000000 --function="upgradeChildContractFromSource" \ + --arguments ${BRIDGE_PROXY} ${NEW_BRIDGE_PROXY_ADDR} 0x00 \ + --send --outfile="upgrade-proxy-child-sc.json" --proxy=${PROXY} --chain=${CHAIN_ID} +} diff --git a/multisig/interaction/config/relayers-snippets.sh b/multisig/interaction/config/relayers-snippets.sh index 3528a641..0ebc5645 100644 --- a/multisig/interaction/config/relayers-snippets.sh +++ b/multisig/interaction/config/relayers-snippets.sh @@ -27,7 +27,7 @@ unstake() { --send --proxy=${PROXY} --chain=${CHAIN_ID} } -stake() { +stakeRelayers() { CHECK_VARIABLES MULTISIG RELAYER_REQUIRED_STAKE \ RELAYER_WALLET0 RELAYER_WALLET1 RELAYER_WALLET2 RELAYER_WALLET3 RELAYER_WALLET4 \ RELAYER_WALLET5 RELAYER_WALLET6 RELAYER_WALLET7 RELAYER_WALLET8 RELAYER_WALLET9 diff --git a/multisig/interaction/config/safe-snippets.sh b/multisig/interaction/config/safe-snippets.sh index 3b2ff1c9..2adf00fd 100644 --- a/multisig/interaction/config/safe-snippets.sh +++ b/multisig/interaction/config/safe-snippets.sh @@ -3,7 +3,7 @@ deploySafe() { mxpy --verbose contract deploy --bytecode=${SAFE_WASM} --recall-nonce --pem=${ALICE} \ --gas-limit=150000000 \ - --arguments ${MULTI_TRANSFER} ${AGGREGATOR} 1 \ + --arguments ${AGGREGATOR} ${MULTI_TRANSFER} 1 \ --send --outfile="deploy-safe-testnet.interaction.json" --proxy=${PROXY} --chain=${CHAIN_ID} || return TRANSACTION=$(mxpy data parse --file="./deploy-safe-testnet.interaction.json" --expression="data['emittedTransactionHash']") @@ -33,4 +33,47 @@ unsetLocalRolesEsdtSafe() { --gas-limit=60000000 --function="unSetSpecialRole" \ --arguments str:${CHAIN_SPECIFIC_TOKEN} ${SAFE} str:ESDTRoleLocalBurn str:ESDTRoleLocalMint \ --send --proxy=${PROXY} --chain=${CHAIN_ID} -} \ No newline at end of file +} + +setBridgedTokensWrapperOnEsdtSafe() { + CHECK_VARIABLES SAFE BRIDGED_TOKENS_WRAPPER + + mxpy --verbose contract call ${SAFE} --recall-nonce --pem=${ALICE} \ + --gas-limit=60000000 --function="setBridgedTokensWrapperAddress" \ + --arguments ${BRIDGED_TOKENS_WRAPPER} \ + --send --proxy=${PROXY} --chain=${CHAIN_ID} +} + +setSCProxyOnEsdtSafe() { + CHECK_VARIABLES SAFE BRIDGE_PROXY + + mxpy --verbose contract call ${SAFE} --recall-nonce --pem=${ALICE} \ + --gas-limit=60000000 --function="setBridgeProxyContractAddress" \ + --arguments ${BRIDGE_PROXY} \ + --send --proxy=${PROXY} --chain=${CHAIN_ID} +} + +deploySafeForUpgrade() { + CHECK_VARIABLES SAFE_WASM MULTI_TRANSFER AGGREGATOR BRIDGE_PROXY + + mxpy --verbose contract deploy --bytecode=${SAFE_WASM} --recall-nonce --pem=${ALICE} \ + --gas-limit=150000000 \ + --arguments ${AGGREGATOR} ${MULTI_TRANSFER} 1 \ + --send --outfile="deploy-safe-upgrade.interaction.json" --proxy=${PROXY} --chain=${CHAIN_ID} || return + + TRANSACTION=$(mxpy data parse --file="./deploy-safe-upgrade.interaction.json" --expression="data['emittedTransactionHash']") + ADDRESS=$(mxpy data parse --file="./deploy-safe-upgrade.interaction.json" --expression="data['contractAddress']") + + echo "" + echo "New safe contract address: ${ADDRESS}" +} + +upgradeSafeContract() { + local NEW_SAFE_ADDR=$(mxpy data parse --file="./deploy-safe-upgrade.interaction.json" --expression="data['contractAddress']") + + mxpy --verbose contract call ${MULTISIG} --recall-nonce --pem=${ALICE} \ + --gas-limit=400000000 --function="upgradeChildContractFromSource" \ + --arguments ${SAFE} ${NEW_SAFE_ADDR} 0x00 \ + ${AGGREGATOR} ${MULTI_TRANSFER} ${BRIDGE_PROXY} 1 \ + --send --outfile="upgrade-safe-child-sc.json" --proxy=${PROXY} --chain=${CHAIN_ID} +} diff --git a/multisig/interaction/config/testing.sh b/multisig/interaction/config/testing.sh new file mode 100644 index 00000000..f1777daf --- /dev/null +++ b/multisig/interaction/config/testing.sh @@ -0,0 +1,71 @@ +deployFaucet() { + CHECK_VARIABLES FAUCET_WASM ALICE + + mxpy --verbose contract deploy --bytecode=${FAUCET_WASM} --recall-nonce --pem=${ALICE} \ + --gas-limit=20000000 \ + --send --outfile=deploy-faucet-testnet.interaction.json --proxy=${PROXY} --chain=${CHAIN_ID} || return + + TRANSACTION=$(mxpy data parse --file="./deploy-faucet-testnet.interaction.json" --expression="data['emittedTransactionHash']") + ADDRESS=$(mxpy data parse --file="./deploy-faucet-testnet.interaction.json" --expression="data['contractAddress']") + + mxpy data store --key=address-testnet-faucet --value=${ADDRESS} + mxpy data store --key=deployTransaction-testnet --value=${TRANSACTION} + + echo "" + echo "Faucet: ${ADDRESS}" + update-config FAUCET ${ADDRESS} +} + +setMintRoleForUniversalToken() { + CHECK_VARIABLES ALICE ALICE_ADDRESS + + mxpy --verbose contract call ${ESDT_SYSTEM_SC_ADDRESS} --recall-nonce --pem=${ALICE} \ + --gas-limit=60000000 --function="setSpecialRole" \ + --arguments str:${UNIVERSAL_TOKEN} ${ALICE_ADDRESS} str:ESDTRoleLocalMint \ + --send --proxy=${PROXY} --chain=${CHAIN_ID} +} + +mintAndDeposit() { + CHECK_VARIABLES ALICE ALICE_ADDRESS FAUCET + + read -p "Amount to mint (without decimals): " AMOUNT_TO_MINT + VALUE_TO_MINT=$(echo "scale=0; $AMOUNT_TO_MINT*10^$NR_DECIMALS_UNIVERSAL/1" | bc) + mxpy --verbose contract call ${ALICE_ADDRESS} --recall-nonce --pem=${ALICE} \ + --gas-limit=300000 --function="ESDTLocalMint" \ + --arguments str:${UNIVERSAL_TOKEN} ${VALUE_TO_MINT} \ + --send --proxy=${PROXY} --chain=${CHAIN_ID} + + sleep 6 + + mxpy --verbose contract call ${FAUCET} --recall-nonce --pem=${ALICE} \ + --gas-limit=5000000 --function="ESDTTransfer" \ + --arguments str:${UNIVERSAL_TOKEN} ${VALUE_TO_MINT} str:deposit 100 \ + --send --proxy=${PROXY} --chain=${CHAIN_ID} +} + +unSetMintRoleForUniversalToken() { + CHECK_VARIABLES ALICE ALICE_ADDRESS ESDT_SYSTEM_SC_ADDRESS + + mxpy --verbose contract call ${ESDT_SYSTEM_SC_ADDRESS} --recall-nonce --pem=${ALICE} \ + --gas-limit=60000000 --function="unSetSpecialRole" \ + --arguments str:${UNIVERSAL_TOKEN} ${ALICE_ADDRESS} str:ESDTRoleLocalMint \ + --send --proxy=${PROXY} --chain=${CHAIN_ID} +} + +deployTestCaller() { + CHECK_VARIABLES TEST_CALLER_WASM ALICE + + mxpy --verbose contract deploy --bytecode=${TEST_CALLER_WASM} --recall-nonce --pem=${ALICE} \ + --gas-limit=20000000 \ + --send --outfile=deploy-test-caller.interaction.json --proxy=${PROXY} --chain=${CHAIN_ID} || return + + TRANSACTION=$(mxpy data parse --file="./deploy-test-caller.interaction.json" --expression="data['emittedTransactionHash']") + ADDRESS=$(mxpy data parse --file="./deploy-test-caller.interaction.json" --expression="data['contractAddress']") + + mxpy data store --key=address-test-caller --value=${ADDRESS} + mxpy data store --key=deployTransaction-testnet --value=${TRANSACTION} + + echo "" + echo "Test caller: ${ADDRESS}" + update-config TEST_CALLER ${ADDRESS} +} diff --git a/multisig/interaction/config/upgrade-snippets.sh b/multisig/interaction/config/upgrade-snippets.sh deleted file mode 100644 index 60c9fa62..00000000 --- a/multisig/interaction/config/upgrade-snippets.sh +++ /dev/null @@ -1,60 +0,0 @@ -#TODO: check & updates upgrade snippets -deploySafeForUpgrade() { - getAggregatorAddressHex - - local ESDT_SAFE_ETH_TX_GAS_LIMIT=20000 # gives us 200$ for multiversx->eth - - mxpy --verbose contract deploy --project=${PROJECT_SAFE} --recall-nonce --pem=${ALICE} \ - --gas-limit=150000000 \ - --arguments 0x${AGGREGATOR_ADDRESS_HEX} ${ESDT_SAFE_ETH_TX_GAS_LIMIT} \ - --send --outfile="deploy-safe-upgrade.interaction.json" --proxy=${PROXY} --chain=${CHAIN_ID} || return - - ADDRESS=$(mxpy data parse --file="./deploy-safe-upgrade.interaction.json" --expression="data['contractAddress']") - - echo "" - echo "Safe contract address: ${ADDRESS}" -} - - -upgradeSafeContract() { - getEsdtSafeAddressHex - getAggregatorAddressHex - local ESDT_SAFE_ETH_TX_GAS_LIMIT=20000 - - local NEW_SAFE_BECH=$(mxpy data parse --file="./deploy-safe-upgrade.interaction.json" --expression="data['contractAddress']") - local NEW_SAFE_ADDR=$(mxpy wallet bech32 --decode $NEW_SAFE_BECH) - - - - mxpy --verbose contract call ${ADDRESS} --recall-nonce --pem=${ALICE} \ - --gas-limit=400000000 --function="upgradeChildContractFromSource" \ - --arguments 0x${ESDT_SAFE_ADDRESS_HEX} 0x${NEW_SAFE_ADDR} 0x00 \ - 0x${AGGREGATOR_ADDRESS_HEX} ${ESDT_SAFE_ETH_TX_GAS_LIMIT} \ - --send --outfile="upgradesafe-child-sc-spam.json" --proxy=${PROXY} --chain=${CHAIN_ID} -} - -upgrade() { - mxpy --verbose contract upgrade ${ADDRESS} --project=${PROJECT} --recall-nonce --pem=${ALICE} \ - --gas-limit=100000000 --send --outfile="upgrade.json" --proxy=${PROXY} --chain=${CHAIN_ID} || return -} - -upgradeMultisig() { - CHECK_VARIABLES RELAYER_ADDR_0 RELAYER_ADDR_1 RELAYER_ADDR_2 RELAYER_ADDR_3 \ - RELAYER_ADDR_4 RELAYER_ADDR_5 RELAYER_ADDR_6 RELAYER_ADDR_7 RELAYER_ADDR_8 \ - RELAYER_ADDR_9 SAFE MULTI_TRANSFER RELAYER_REQUIRED_STAKE SLASH_AMOUNT QUORUM MULTISIG MULTISIG_WASM - - MIN_STAKE=$(echo "$RELAYER_REQUIRED_STAKE*10^18" | bc) - mxpy --verbose contract upgrade ${MULTISIG} --bytecode=${MULTISIG_WASM} --recall-nonce --pem=${ALICE} \ - --gas-limit=200000000 \ - --arguments ${SAFE} ${MULTI_TRANSFER} ${BRIDGE_PROXY} \ - --send --outfile="deploy-testnet.interaction.json" --proxy=${PROXY} --chain=${CHAIN_ID} || return - - TRANSACTION=$(mxpy data parse --file="./deploy-testnet.interaction.json" --expression="data['emitted_tx']['hash']") - ADDRESS=$(mxpy data parse --file="./deploy-testnet.interaction.json" --expression="data['contractAddress']") - - mxpy data store --key=address-testnet-multisig --value=${ADDRESS} - mxpy data store --key=deployTransaction-testnet --value=${TRANSACTION} - - echo "" - echo "Multisig contract address: ${ADDRESS}" -} \ No newline at end of file diff --git a/multisig/interaction/config/wrapped-snippets.sh b/multisig/interaction/config/wrapped-snippets.sh index 762eb5be..87a1fc0e 100644 --- a/multisig/interaction/config/wrapped-snippets.sh +++ b/multisig/interaction/config/wrapped-snippets.sh @@ -9,7 +9,7 @@ deployBridgedTokensWrapper() { CHECK_VARIABLES BRIDGED_TOKENS_WRAPPER_WASM mxpy --verbose contract deploy --bytecode=${BRIDGED_TOKENS_WRAPPER_WASM} --recall-nonce --pem=${ALICE} \ - --gas-limit=40000000 \ + --gas-limit=60000000 \ --send --outfile="deploy-bridged-tokens-wrapper-testnet.interaction.json" --proxy=${PROXY} --chain=${CHAIN_ID} || return TRANSACTION=$(mxpy data parse --file="./deploy-bridged-tokens-wrapper-testnet.interaction.json" --expression="data['emittedTransactionHash']") @@ -130,7 +130,7 @@ wrapper-upgrade() { } setEsdtSafeOnWrapper() { - CHECK_VARIABLES BRIDGED_TOKENS_WRAPPER BRIDGED_TOKENS_WRAPPER + CHECK_VARIABLES BRIDGED_TOKENS_WRAPPER SAFE mxpy --verbose contract call ${BRIDGED_TOKENS_WRAPPER} --recall-nonce --pem=${ALICE} \ --gas-limit=60000000 --function="setEsdtSafeContractAddress" \ diff --git a/multisig/interaction/script.sh b/multisig/interaction/script.sh index 36ae170a..84e5fb17 100755 --- a/multisig/interaction/script.sh +++ b/multisig/interaction/script.sh @@ -13,10 +13,6 @@ case "$1" in confirmation deploy-bridge-contracts ;; -'upgrade-wrapper') - confirmation upgrade-wrapper - ;; - 'add-relayer') confirmation addBoardMember ;; @@ -87,13 +83,58 @@ case "$1" in confirmation upgrade-wrapper-chain-specific-token ;; +'init-supply-mint-burn') + confirmation init-supply-mint-burn + ;; + +'upgrade-aggregator') + confirmation upgrade-aggregator + ;; + +'upgrade-wrapper') + confirmation upgrade-wrapper + ;; + +'upgrade-safe') + confirmation upgrade-safe + ;; + +'upgrade-multi-transfer') + confirmation upgrade-multi-transfer + ;; + +'upgrade-proxy') + confirmation upgrade-proxy + ;; + +'upgrade-multisig') + confirmation upgrade-multisig + ;; + +'whitelist-native-token') + confirmation whitelist-native-token + ;; + +'faucet-deposit') + confirmation faucet-deposit + ;; + +'deploy-test-caller') + confirmation deploy-test-caller + ;; + *) echo "Usage: Invalid choice: '"$1"'" echo -e echo "Choose from:" - echo " { \"whitelist-token\", \"deploy-bridge-contracts\", \"upgrade-wrapper\", \"add-relayer\", \"remove-relayer\", " - echo " \"remove-whitelist-token\", \"set-safe-max-tx\", \"set-safe-batch-block-duration\", \"change-quorum\", \"pause-contracts\", \"unpause-contracts\", " - echo " \"set-swap-fee\", \"mint-chain-specific\", \"upgrade-wrapper-universal-token\", \"upgrade-wrapper-chain-specific-token\" }" + echo " { \"deploy-bridge-contracts\", " + echo " \"upgrade-aggregator\", \"upgrade-wrapper\", \"upgrade-safe\", \"upgrade-multi-transfer\", \"upgrade-proxy\", \"upgrade-multisig\" " + echo " \"pause-contracts\", \"unpause-contracts\", \"add-relayer\", \"remove-relayer\", " + echo " \"set-safe-max-tx\", \"set-safe-batch-block-duration\", \"change-quorum\", \"set-swap-fee\", " + echo " \"whitelist-token\", \"whitelist-native-token\", \"remove-whitelist-token\", \"upgrade-wrapper-universal-token\", \"upgrade-wrapper-chain-specific-token\", " + echo " \"mint-chain-specific\", \"init-supply-mint-burn\", " + echo " \"faucet-deposit\", \"deploy-test-caller\"" + echo " } " ;; esac \ No newline at end of file diff --git a/multisig/scenarios/ethereum_to_multiversx_relayer_call_data_several_tx_test.scen.json b/multisig/scenarios/ethereum_to_multiversx_relayer_call_data_several_tx_test.scen.json index 7b0f2087..fbb56f5e 100644 --- a/multisig/scenarios/ethereum_to_multiversx_relayer_call_data_several_tx_test.scen.json +++ b/multisig/scenarios/ethereum_to_multiversx_relayer_call_data_several_tx_test.scen.json @@ -43,6 +43,7 @@ "arguments": [ "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000005006d756c74692d7472616e736665725f5f5f5f5f5f5f5f", + "0x000000000000000005006272696467652d70726f78795f5f5f5f5f5f5f5f5f5f", "0x0249f0" ], "gasLimit": "5,000,000" diff --git a/multisig/scenarios/ethereum_to_multiversx_relayer_query2_test.scen.json b/multisig/scenarios/ethereum_to_multiversx_relayer_query2_test.scen.json index d1eca544..78291d1c 100644 --- a/multisig/scenarios/ethereum_to_multiversx_relayer_query2_test.scen.json +++ b/multisig/scenarios/ethereum_to_multiversx_relayer_query2_test.scen.json @@ -43,6 +43,7 @@ "arguments": [ "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000005006d756c74692d7472616e736665725f5f5f5f5f5f5f5f", + "0x000000000000000005006272696467652d70726f78795f5f5f5f5f5f5f5f5f5f", "0x0249f0" ], "gasLimit": "5,000,000" diff --git a/multisig/scenarios/ethereum_to_multiversx_relayer_query_test.scen.json b/multisig/scenarios/ethereum_to_multiversx_relayer_query_test.scen.json index edb4eceb..b00b780f 100644 --- a/multisig/scenarios/ethereum_to_multiversx_relayer_query_test.scen.json +++ b/multisig/scenarios/ethereum_to_multiversx_relayer_query_test.scen.json @@ -43,6 +43,7 @@ "arguments": [ "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000005006d756c74692d7472616e736665725f5f5f5f5f5f5f5f", + "0x000000000000000005006272696467652d70726f78795f5f5f5f5f5f5f5f5f5f", "0x0249f0" ], "gasLimit": "5,000,000" diff --git a/multisig/scenarios/ethereum_to_multiversx_tx_batch_ok_call_data_encoded.scen.json b/multisig/scenarios/ethereum_to_multiversx_tx_batch_ok_call_data_encoded.scen.json index 3b307365..84ec33e6 100644 --- a/multisig/scenarios/ethereum_to_multiversx_tx_batch_ok_call_data_encoded.scen.json +++ b/multisig/scenarios/ethereum_to_multiversx_tx_batch_ok_call_data_encoded.scen.json @@ -43,6 +43,7 @@ "arguments": [ "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000005006d756c74692d7472616e736665725f5f5f5f5f5f5f5f", + "0x000000000000000005006272696467652d70726f78795f5f5f5f5f5f5f5f5f5f", "0x0249f0" ], "gasLimit": "5,000,000" diff --git a/multisig/src/bridge_proxy_contract_proxy.rs b/multisig/src/bridge_proxy_contract_proxy.rs index 842e5d22..768889b6 100644 --- a/multisig/src/bridge_proxy_contract_proxy.rs +++ b/multisig/src/bridge_proxy_contract_proxy.rs @@ -87,13 +87,16 @@ where { pub fn deposit< Arg0: ProxyArg>, + Arg1: ProxyArg, >( self, eth_tx: Arg0, + batch_id: Arg1, ) -> TxTypedCall { self.wrapped_tx .raw_call("deposit") .argument(ð_tx) + .argument(&batch_id) .original_result() } @@ -110,16 +113,12 @@ where .original_result() } - pub fn cancel< - Arg0: ProxyArg, - >( + pub fn update_lowest_tx_id( self, - tx_id: Arg0, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) - .raw_call("cancel") - .argument(&tx_id) + .raw_call("updateLowestTxId") .original_result() } diff --git a/multisig/src/bridged_tokens_wrapper_proxy.rs b/multisig/src/bridged_tokens_wrapper_proxy.rs index 852e4057..df5b7a63 100644 --- a/multisig/src/bridged_tokens_wrapper_proxy.rs +++ b/multisig/src/bridged_tokens_wrapper_proxy.rs @@ -206,18 +206,15 @@ where pub fn unwrap_token_create_transaction< Arg0: ProxyArg>, Arg1: ProxyArg>, - Arg2: ProxyArg>>, >( self, requested_token: Arg0, to: Arg1, - opt_refunding_address: Arg2, ) -> TxTypedCall { self.wrapped_tx .raw_call("unwrapTokenCreateTransaction") .argument(&requested_token) .argument(&to) - .argument(&opt_refunding_address) .original_result() } @@ -234,19 +231,6 @@ where .original_result() } - pub fn set_bridge_proxy_contract_address< - Arg0: ProxyArg>>, - >( - self, - opt_new_address: Arg0, - ) -> TxTypedCall { - self.wrapped_tx - .payment(NotPayable) - .raw_call("setBridgeProxyContractAddress") - .argument(&opt_new_address) - .original_result() - } - pub fn universal_bridged_token_ids( self, ) -> TxTypedCall>> { @@ -304,15 +288,6 @@ where .original_result() } - pub fn bridge_proxy_contract_address( - self, - ) -> TxTypedCall> { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getBridgeProxyContractAddress") - .original_result() - } - pub fn pause_endpoint( self, ) -> TxTypedCall { diff --git a/multisig/src/esdt_safe_proxy.rs b/multisig/src/esdt_safe_proxy.rs index 6de0d968..59e564f3 100644 --- a/multisig/src/esdt_safe_proxy.rs +++ b/multisig/src/esdt_safe_proxy.rs @@ -80,18 +80,21 @@ where pub fn upgrade< Arg0: ProxyArg>, Arg1: ProxyArg>, - Arg2: ProxyArg>, + Arg2: ProxyArg>, + Arg3: ProxyArg>, >( self, fee_estimator_contract_address: Arg0, multi_transfer_contract_address: Arg1, - eth_tx_gas_limit: Arg2, + bridge_proxy_contract_address: Arg2, + eth_tx_gas_limit: Arg3, ) -> TxTypedUpgrade { self.wrapped_tx .payment(NotPayable) .raw_upgrade() .argument(&fee_estimator_contract_address) .argument(&multi_transfer_contract_address) + .argument(&bridge_proxy_contract_address) .argument(ð_tx_gas_limit) .original_result() } @@ -152,16 +155,16 @@ where /// fee_amount = price_per_gas_unit * eth_tx_gas_limit pub fn create_transaction< Arg0: ProxyArg>, - Arg1: ProxyArg>>, + Arg1: ProxyArg>>, >( self, to: Arg0, - opt_refund_address: Arg1, + opt_refund_info: Arg1, ) -> TxTypedCall { self.wrapped_tx .raw_call("createTransaction") .argument(&to) - .argument(&opt_refund_address) + .argument(&opt_refund_info) .original_result() } @@ -212,16 +215,48 @@ where .original_result() } - pub fn withdraw_total_fees_on_ethereum< + pub fn set_bridge_proxy_contract_address< + Arg0: ProxyArg>>, + >( + self, + opt_new_address: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("setBridgeProxyContractAddress") + .argument(&opt_new_address) + .original_result() + } + + pub fn withdraw_refund_fees_for_ethereum< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( + self, + token_id: Arg0, + multisig_owner: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("withdrawRefundFeesForEthereum") + .argument(&token_id) + .argument(&multisig_owner) + .original_result() + } + + pub fn withdraw_transaction_fees< Arg0: ProxyArg>, + Arg1: ProxyArg>, >( self, token_id: Arg0, + multisig_owner: Arg1, ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) - .raw_call("withdrawTotalFeesOnEthereum") + .raw_call("withdrawTransactionFees") .argument(&token_id) + .argument(&multisig_owner) .original_result() } @@ -265,6 +300,32 @@ where .original_result() } + pub fn get_refund_fees_for_ethereum< + Arg0: ProxyArg>, + >( + self, + token_id: Arg0, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getRefundFeesForEthereum") + .argument(&token_id) + .original_result() + } + + pub fn get_transaction_fees< + Arg0: ProxyArg>, + >( + self, + token_id: Arg0, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getTransactionFees") + .argument(&token_id) + .original_result() + } + pub fn bridged_tokens_wrapper_address( self, ) -> TxTypedCall> { @@ -274,6 +335,15 @@ where .original_result() } + pub fn bridge_proxy_contract_address( + self, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getBridgeProxyContractAddress") + .original_result() + } + pub fn set_fee_estimator_contract_address< Arg0: ProxyArg>, >( @@ -745,3 +815,14 @@ where .original_result() } } + +#[type_abi] +#[derive(TopEncode, TopDecode, NestedEncode, NestedDecode, Clone, ManagedVecItem, PartialEq)] +pub struct RefundInfo +where + Api: ManagedTypeApi, +{ + pub address: ManagedAddress, + pub initial_batch_id: u64, + pub initial_nonce: u64, +} diff --git a/multisig/src/lib.rs b/multisig/src/lib.rs index 00e1b599..d8aecf3a 100644 --- a/multisig/src/lib.rs +++ b/multisig/src/lib.rs @@ -342,22 +342,38 @@ pub trait Multisig: } #[only_owner] - #[endpoint(withdrawTotalFeesOnEthereum)] - fn withdraw_total_fees_on_ethereum(&self, token_id: TokenIdentifier) { + #[endpoint(withdrawRefundFeesForEthereum)] + fn withdraw_refund_fees_for_ethereum(&self, token_id: TokenIdentifier) { let esdt_safe_addr = self.esdt_safe_address().get(); + let multisig_owner = self.blockchain().get_owner_address(); self.tx() .to(esdt_safe_addr) .typed(esdt_safe_proxy::EsdtSafeProxy) - .withdraw_total_fees_on_ethereum(token_id) + .withdraw_refund_fees_for_ethereum(token_id, multisig_owner) + .sync_call(); + } + + #[only_owner] + #[endpoint(withdrawTransactionFees)] + fn withdraw_transaction_fees(&self, token_id: TokenIdentifier) { + let esdt_safe_addr = self.esdt_safe_address().get(); + let multisig_owner = self.blockchain().get_owner_address(); + + self.tx() + .to(esdt_safe_addr) + .typed(esdt_safe_proxy::EsdtSafeProxy) + .withdraw_transaction_fees(token_id, multisig_owner) .sync_call(); } #[only_owner] #[endpoint(withdrawSlashedAmount)] fn withdraw_slashed_amount(&self) { - let slashed_amount = self.slashed_tokens_amount().get(); + let slashed_tokens_amount_mapper = self.slashed_tokens_amount(); + let slashed_amount = slashed_tokens_amount_mapper.get(); self.tx().to(ToCaller).egld(&slashed_amount).transfer(); + slashed_tokens_amount_mapper.clear(); } /// Proposers and board members use this to launch signed actions. diff --git a/multisig/src/multisig_proxy.rs b/multisig/src/multisig_proxy.rs index f73fcb88..a652c8ba 100644 --- a/multisig/src/multisig_proxy.rs +++ b/multisig/src/multisig_proxy.rs @@ -237,7 +237,7 @@ where .original_result() } - pub fn withdraw_total_fees_on_ethereum< + pub fn withdraw_refund_fees_for_ethereum< Arg0: ProxyArg>, >( self, @@ -245,7 +245,20 @@ where ) -> TxTypedCall { self.wrapped_tx .payment(NotPayable) - .raw_call("withdrawTotalFeesOnEthereum") + .raw_call("withdrawRefundFeesForEthereum") + .argument(&token_id) + .original_result() + } + + pub fn withdraw_transaction_fees< + Arg0: ProxyArg>, + >( + self, + token_id: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("withdrawTransactionFees") .argument(&token_id) .original_result() } diff --git a/multisig/tests/multisig_blackbox_test.rs b/multisig/tests/multisig_blackbox_test.rs index 7785822e..eb3df1a9 100644 --- a/multisig/tests/multisig_blackbox_test.rs +++ b/multisig/tests/multisig_blackbox_test.rs @@ -207,6 +207,7 @@ impl MultiTransferTestState { .upgrade( ManagedAddress::zero(), MULTI_TRANSFER_ADDRESS.to_address(), + BRIDGE_PROXY_ADDRESS.to_address(), ESDT_SAFE_ETH_TX_GAS_LIMIT, ) .code(ESDT_SAFE_CODE_PATH) diff --git a/multisig/wasm/src/lib.rs b/multisig/wasm/src/lib.rs index df37753e..d7138aaa 100644 --- a/multisig/wasm/src/lib.rs +++ b/multisig/wasm/src/lib.rs @@ -6,9 +6,9 @@ // Init: 1 // Upgrade: 1 -// Endpoints: 73 +// Endpoints: 74 // Async Callback (empty): 1 -// Total number of exported functions: 76 +// Total number of exported functions: 77 #![no_std] @@ -28,7 +28,8 @@ multiversx_sc_wasm_adapter::endpoints! { moveRefundBatchToSafeFromChildContract => move_refund_batch_to_safe_from_child_contract initSupplyFromChildContract => init_supply_from_child_contract addUnprocessedRefundTxToBatch => add_unprocessed_refund_tx_to_batch - withdrawTotalFeesOnEthereum => withdraw_total_fees_on_ethereum + withdrawRefundFeesForEthereum => withdraw_refund_fees_for_ethereum + withdrawTransactionFees => withdraw_transaction_fees withdrawSlashedAmount => withdraw_slashed_amount performAction => perform_action_endpoint sign => sign