diff --git a/Cargo.lock b/Cargo.lock index e5cd9391..dc8afe16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -676,10 +676,13 @@ name = "esdt-safe" version = "0.0.0" dependencies = [ "bls-signature", + "hex", "max-bridged-amount-module", "multiversx-sc", "multiversx-sc-modules", "multiversx-sc-scenario", + "num-bigint", + "num-traits", "token-module", "transaction", "tx-batch-module", diff --git a/common/tx-batch-module/src/lib.rs b/common/tx-batch-module/src/lib.rs index 1ecbf89b..527f2795 100644 --- a/common/tx-batch-module/src/lib.rs +++ b/common/tx-batch-module/src/lib.rs @@ -4,13 +4,10 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); pub use batch_status::BatchStatus; -use transaction::{ - BatchId, GasLimit, Transaction, TxBatchSplitInFields, TxNonce, MIN_BLOCKS_FOR_FINALITY, -}; +use transaction::{BatchId, Transaction, TxBatchSplitInFields, TxNonce, MIN_BLOCKS_FOR_FINALITY}; use tx_batch_mapper::TxBatchMapper; pub const FIRST_BATCH_ID: BatchId = 1; -pub const MAX_GAS_LIMIT_PER_BATCH: GasLimit = 500_000_000; pub mod batch_status; pub mod tx_batch_mapper; @@ -121,30 +118,16 @@ pub trait TxBatchModule { // private fn add_to_batch(&self, transaction: Transaction) -> BatchId { - let default_gas_limit = self.sovereign_tx_gas_limit().get(); let first_batch_id = self.first_batch_id().get(); let last_batch_id = self.last_batch_id().get(); let mut last_batch = self.pending_batches(last_batch_id); - let gas_cost = match &transaction.opt_transfer_data { - Some(transfer_data) => transfer_data.gas_limit, - None => transaction.tokens.len() as u64 * default_gas_limit, - }; - - let gas_cost_mapper = self.total_gas_cost(last_batch_id); - let last_batch_total_gas_cost = gas_cost_mapper.get(); - let new_total_gas_cost = last_batch_total_gas_cost + gas_cost; - - if self.is_batch_full(&last_batch, last_batch_id, first_batch_id) - || new_total_gas_cost > MAX_GAS_LIMIT_PER_BATCH - { + if self.is_batch_full(&last_batch, last_batch_id, first_batch_id) { let (new_batch_id, _) = self.create_new_batch(transaction); - self.total_gas_cost(new_batch_id).set(gas_cost); new_batch_id } else { last_batch.push(transaction); - gas_cost_mapper.set(new_total_gas_cost); last_batch_id } @@ -159,37 +142,21 @@ pub trait TxBatchModule { return ManagedVec::new(); } - let default_gas_limit = self.sovereign_tx_gas_limit().get(); let first_batch_id = self.first_batch_id().get(); let mut last_batch_id = self.last_batch_id().get(); let mut last_batch = self.pending_batches(last_batch_id); let mut batch_ids = ManagedVec::new(); - let mut total_gas_cost = self.total_gas_cost(last_batch_id).get(); for tx in transactions { - let gas_cost = match &tx.opt_transfer_data { - Some(transfer_data) => transfer_data.gas_limit, - None => tx.tokens.len() as u64 * default_gas_limit, - }; - - let new_total_gas_cost = total_gas_cost + gas_cost; - if self.is_batch_full(&last_batch, last_batch_id, first_batch_id) - || new_total_gas_cost > MAX_GAS_LIMIT_PER_BATCH - { - self.total_gas_cost(last_batch_id).set(total_gas_cost); - total_gas_cost = gas_cost; - + if self.is_batch_full(&last_batch, last_batch_id, first_batch_id) { (last_batch_id, last_batch) = self.create_new_batch(tx); } else { - total_gas_cost = new_total_gas_cost; last_batch.push(tx); } batch_ids.push(last_batch_id); } - self.total_gas_cost(last_batch_id).set(total_gas_cost); - batch_ids } @@ -297,9 +264,6 @@ pub trait TxBatchModule { #[storage_mapper("pendingBatches")] fn pending_batches(&self, batch_id: BatchId) -> TxBatchMapper; - #[storage_mapper("totalGasCost")] - fn total_gas_cost(&self, batch_id: BatchId) -> SingleValueMapper; - #[storage_mapper("lastTxNonce")] fn last_tx_nonce(&self) -> SingleValueMapper; @@ -310,8 +274,4 @@ pub trait TxBatchModule { #[storage_mapper("maxTxBatchBlockDuration")] fn max_tx_batch_block_duration(&self) -> SingleValueMapper; - - #[view(getSovereignTxGasLimit)] - #[storage_mapper("sovereignTxGasLimit")] - fn sovereign_tx_gas_limit(&self) -> SingleValueMapper; } diff --git a/esdt-safe/Cargo.toml b/esdt-safe/Cargo.toml index 7b469020..86e66651 100644 --- a/esdt-safe/Cargo.toml +++ b/esdt-safe/Cargo.toml @@ -32,3 +32,8 @@ version = "=0.43.5" [dev-dependencies.multiversx-sc-scenario] version = "=0.43.5" + +[dev-dependencies] +num-bigint = "0.4.2" +num-traits = "0.2" +hex = "0.4" diff --git a/esdt-safe/src/from_sovereign/refund.rs b/esdt-safe/src/from_sovereign/refund.rs index 1f7e9cbb..7cd4d021 100644 --- a/esdt-safe/src/from_sovereign/refund.rs +++ b/esdt-safe/src/from_sovereign/refund.rs @@ -4,12 +4,13 @@ multiversx_sc::imports!(); const NFT_AMOUNT: u32 = 1; -pub struct CheckMustRefundArgs { - pub token: EsdtTokenPayment, +pub struct CheckMustRefundArgs<'a, M: ManagedTypeApi> { + pub token: &'a EsdtTokenPayment, pub roles: EsdtLocalRoleFlags, - pub dest: ManagedAddress, + pub dest: &'a ManagedAddress, pub batch_id: BatchId, pub tx_nonce: TxNonce, + pub sc_address: &'a ManagedAddress, pub sc_shard: u32, } @@ -20,16 +21,23 @@ pub trait RefundModule: + max_bridged_amount_module::MaxBridgedAmountModule { fn check_must_refund(&self, args: CheckMustRefundArgs) -> bool { - if args.token.token_nonce == 0 { - if !args.roles.has_role(&EsdtLocalRole::Mint) { + let token_balance = self.blockchain().get_esdt_balance( + args.sc_address, + &args.token.token_identifier, + args.token.token_nonce, + ); + if token_balance < args.token.amount { + if args.token.token_nonce == 0 { + if !args.roles.has_role(&EsdtLocalRole::Mint) { + self.transfer_failed_invalid_token(args.batch_id, args.tx_nonce); + + return true; + } + } else if !self.has_nft_roles(args.token, args.roles) { self.transfer_failed_invalid_token(args.batch_id, args.tx_nonce); return true; } - } else if !self.has_nft_roles(&args.token, args.roles) { - self.transfer_failed_invalid_token(args.batch_id, args.tx_nonce); - - return true; } if self.is_above_max_amount(&args.token.token_identifier, &args.token.amount) { @@ -38,11 +46,8 @@ pub trait RefundModule: return true; } - if self.is_account_same_shard_frozen( - args.sc_shard, - &args.dest, - &args.token.token_identifier, - ) { + if self.is_account_same_shard_frozen(args.sc_shard, args.dest, &args.token.token_identifier) + { self.transfer_failed_frozen_destination_account(args.batch_id, args.tx_nonce); return true; diff --git a/esdt-safe/src/from_sovereign/transfer_tokens.rs b/esdt-safe/src/from_sovereign/transfer_tokens.rs index 5b7f99c4..455ed5e8 100644 --- a/esdt-safe/src/from_sovereign/transfer_tokens.rs +++ b/esdt-safe/src/from_sovereign/transfer_tokens.rs @@ -10,7 +10,7 @@ use crate::from_sovereign::refund::CheckMustRefundArgs; multiversx_sc::imports!(); -const CALLBACK_GAS: GasLimit = 1_000_000; // Increase if not enough +const CALLBACK_GAS: GasLimit = 10_000_000; // Increase if not enough #[multiversx_sc::module] pub trait TransferTokensModule: @@ -32,6 +32,9 @@ pub trait TransferTokensModule: ) { require!(self.not_paused(), "Cannot transfer while paused"); + let next_batch_id = self.next_batch_id().get(); + require!(batch_id == next_batch_id, "Unexpected batch ID"); + let mut successful_tx_list = ManagedVec::new(); let mut all_tokens_to_send = ManagedVec::new(); let mut refund_tx_list = ManagedVec::new(); @@ -51,11 +54,12 @@ pub trait TransferTokensModule: .blockchain() .get_esdt_local_roles(&token.token_identifier); let must_refund_args = CheckMustRefundArgs { - token: token.clone(), + token: &token, roles: token_roles, - dest: sov_tx.to.clone(), + dest: &sov_tx.to, batch_id, tx_nonce: sov_tx.nonce, + sc_address: &own_sc_address, sc_shard, }; let must_refund = self.check_must_refund(must_refund_args); @@ -86,6 +90,8 @@ pub trait TransferTokensModule: self.distribute_payments(batch_id, successful_tx_list, all_tokens_to_send); self.add_multiple_tx_to_batch(&refund_tx_list); + + self.next_batch_id().set(batch_id + 1); } fn mint_tokens( @@ -201,4 +207,7 @@ pub trait TransferTokensModule: } } } + + #[storage_mapper("nextBatchId")] + fn next_batch_id(&self) -> SingleValueMapper; } diff --git a/esdt-safe/src/lib.rs b/esdt-safe/src/lib.rs index 3585ceb4..2f448e88 100644 --- a/esdt-safe/src/lib.rs +++ b/esdt-safe/src/lib.rs @@ -3,7 +3,6 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); -use transaction::GasLimit; use tx_batch_module::FIRST_BATCH_ID; const DEFAULT_MAX_TX_BATCH_SIZE: usize = 10; @@ -29,18 +28,8 @@ pub trait EsdtSafe: + multiversx_sc_modules::pause::PauseModule + multiversx_sc_modules::default_issue_callbacks::DefaultIssueCallbacksModule { - /// sovereign_tx_gas_limit - The gas limit that will be used for transactions on the Sovereign side. - /// In case of SC gas limits, this value is provided by the user - /// Will be used to compute the fees for the transfer #[init] - fn init( - &self, - sovereign_tx_gas_limit: GasLimit, - min_valid_signers: u32, - signers: MultiValueEncoded, - ) { - self.sovereign_tx_gas_limit().set(sovereign_tx_gas_limit); - + fn init(&self, min_valid_signers: u32, signers: MultiValueEncoded) { self.max_tx_batch_size().set(DEFAULT_MAX_TX_BATCH_SIZE); self.max_tx_batch_block_duration() .set(DEFAULT_MAX_TX_BATCH_BLOCK_DURATION); @@ -48,6 +37,7 @@ pub trait EsdtSafe: // batch ID 0 is considered invalid self.first_batch_id().set(FIRST_BATCH_ID); self.last_batch_id().set(FIRST_BATCH_ID); + self.next_batch_id().set(FIRST_BATCH_ID); self.set_min_valid_signers(min_valid_signers); self.add_signers(signers); diff --git a/esdt-safe/tests/bridge_setup/mod.rs b/esdt-safe/tests/bridge_setup/mod.rs new file mode 100644 index 00000000..a8c68b54 --- /dev/null +++ b/esdt-safe/tests/bridge_setup/mod.rs @@ -0,0 +1,76 @@ +use bls_signature::BLS_SIGNATURE_LEN; +use esdt_safe::EsdtSafe; +use multiversx_sc::types::{Address, MultiValueEncoded}; +use multiversx_sc_modules::pause::PauseModule; +use multiversx_sc_scenario::{ + managed_token_id, rust_biguint, + testing_framework::{BlockchainStateWrapper, ContractObjWrapper}, + DebugApi, +}; +use token_module::TokenModule; +use tx_batch_module::TxBatchModule; + +multiversx_sc::derive_imports!(); + +pub static FUNGIBLE_TOKEN_ID: &[u8] = b"FUNGTOKEN-123456"; +pub static NFT_TOKEN_ID: &[u8] = b"NFT-123456"; +pub const TOKEN_BALANCE: u64 = 1_000_000_000_000_000_000; +pub static DUMMY_SIG: [u8; BLS_SIGNATURE_LEN] = [0; BLS_SIGNATURE_LEN]; + +#[derive(TopEncode, TopDecode, PartialEq, Debug)] +pub struct DummyAttributes { + pub dummy: u8, +} + +pub struct BridgeSetup +where + BridgeBuilder: 'static + Copy + Fn() -> esdt_safe::ContractObj, +{ + pub b_mock: BlockchainStateWrapper, + pub owner: Address, + pub user: Address, + pub sov_dest_addr: Address, + pub bridge_wrapper: ContractObjWrapper, BridgeBuilder>, +} + +impl BridgeSetup +where + BridgeBuilder: 'static + Copy + Fn() -> esdt_safe::ContractObj, +{ + pub fn new(bridge_builder: BridgeBuilder) -> Self { + let rust_zero = rust_biguint!(0); + let mut b_mock = BlockchainStateWrapper::new(); + let owner = b_mock.create_user_account(&rust_zero); + let user = b_mock.create_user_account(&rust_zero); + let sov_dest_addr = b_mock.create_user_account(&rust_zero); + let bridge_wrapper = + b_mock.create_sc_account(&rust_zero, Some(&owner), bridge_builder, "bridge"); + + b_mock.set_esdt_balance(&user, FUNGIBLE_TOKEN_ID, &rust_biguint!(TOKEN_BALANCE)); + b_mock.set_nft_balance( + &user, + NFT_TOKEN_ID, + 1, + &rust_biguint!(TOKEN_BALANCE), + &DummyAttributes { dummy: 42 }, + ); + + b_mock + .execute_tx(&owner, &bridge_wrapper, &rust_zero, |sc| { + sc.init(0, MultiValueEncoded::new()); + sc.set_max_tx_batch_size(1); + sc.set_paused(false); + sc.add_token_to_whitelist(managed_token_id!(FUNGIBLE_TOKEN_ID)); + sc.add_token_to_whitelist(managed_token_id!(NFT_TOKEN_ID)); + }) + .assert_ok(); + + BridgeSetup { + b_mock, + owner, + user, + sov_dest_addr, + bridge_wrapper, + } + } +} diff --git a/esdt-safe/tests/bridge_test.rs b/esdt-safe/tests/bridge_test.rs new file mode 100644 index 00000000..7515514c --- /dev/null +++ b/esdt-safe/tests/bridge_test.rs @@ -0,0 +1,350 @@ +#![allow(deprecated)] + +use bls_signature::BlsSignature; +use bridge_setup::{ + BridgeSetup, DummyAttributes, DUMMY_SIG, FUNGIBLE_TOKEN_ID, NFT_TOKEN_ID, TOKEN_BALANCE, +}; +use esdt_safe::{ + from_sovereign::transfer_tokens::TransferTokensModule, + to_sovereign::{ + create_tx::CreateTxModule, refund::RefundModule, set_tx_status::SetTxStatusModule, + }, +}; +use multiversx_sc::{ + codec::multi_types::OptionalValue, + types::{EsdtTokenPayment, ManagedVec, MultiValueEncoded}, +}; +use multiversx_sc_scenario::{ + managed_address, managed_biguint, managed_token_id, rust_biguint, + testing_framework::TxTokenTransfer, +}; +use transaction::{ + transaction_status::TransactionStatus, StolenFromFrameworkEsdtTokenData, Transaction, +}; +use tx_batch_module::TxBatchModule; + +mod bridge_setup; + +#[test] +fn init_test() { + let _ = BridgeSetup::new(esdt_safe::contract_obj); +} + +#[test] +fn transfer_two_tokens_to_sov_ok() { + let mut bridge_setup = BridgeSetup::new(esdt_safe::contract_obj); + + let transfers = [ + TxTokenTransfer { + token_identifier: FUNGIBLE_TOKEN_ID.to_vec(), + nonce: 0, + value: rust_biguint!(1_000), + }, + TxTokenTransfer { + token_identifier: NFT_TOKEN_ID.to_vec(), + nonce: 1, + value: rust_biguint!(2_000), + }, + ]; + + let dest = bridge_setup.sov_dest_addr.clone(); + + bridge_setup + .b_mock + .execute_esdt_multi_transfer( + &bridge_setup.user, + &bridge_setup.bridge_wrapper, + &transfers, + |sc| { + sc.create_transaction(managed_address!(&dest), OptionalValue::None); + }, + ) + .assert_ok(); + + bridge_setup + .b_mock + .execute_tx( + &bridge_setup.owner, + &bridge_setup.bridge_wrapper, + &rust_biguint!(0), + |sc| { + let mut statuses = MultiValueEncoded::new(); + statuses.push(TransactionStatus::Executed); + + sc.set_transaction_batch_status( + 1, + BlsSignature::new_from_bytes(&DUMMY_SIG), + statuses, + ); + }, + ) + .assert_ok(); +} + +#[test] +fn refund_failed_tx_to_sov() { + let mut bridge_setup = BridgeSetup::new(esdt_safe::contract_obj); + + let transfers = [ + TxTokenTransfer { + token_identifier: FUNGIBLE_TOKEN_ID.to_vec(), + nonce: 0, + value: rust_biguint!(1_000), + }, + TxTokenTransfer { + token_identifier: NFT_TOKEN_ID.to_vec(), + nonce: 1, + value: rust_biguint!(2_000), + }, + ]; + + let dest = bridge_setup.sov_dest_addr.clone(); + + bridge_setup + .b_mock + .execute_esdt_multi_transfer( + &bridge_setup.user, + &bridge_setup.bridge_wrapper, + &transfers, + |sc| { + sc.create_transaction(managed_address!(&dest), OptionalValue::None); + }, + ) + .assert_ok(); + + bridge_setup + .b_mock + .execute_tx( + &bridge_setup.owner, + &bridge_setup.bridge_wrapper, + &rust_biguint!(0), + |sc| { + let mut statuses = MultiValueEncoded::new(); + statuses.push(TransactionStatus::Rejected); + + sc.set_transaction_batch_status( + 1, + BlsSignature::new_from_bytes(&DUMMY_SIG), + statuses, + ); + }, + ) + .assert_ok(); + + bridge_setup + .b_mock + .execute_tx( + &bridge_setup.user, + &bridge_setup.bridge_wrapper, + &rust_biguint!(0), + |sc| { + sc.claim_refund(managed_token_id!(FUNGIBLE_TOKEN_ID)); + sc.claim_refund(managed_token_id!(NFT_TOKEN_ID)); + }, + ) + .assert_ok(); + + bridge_setup.b_mock.check_esdt_balance( + &bridge_setup.user, + FUNGIBLE_TOKEN_ID, + &rust_biguint!(TOKEN_BALANCE), + ); + bridge_setup.b_mock.check_nft_balance( + &bridge_setup.user, + NFT_TOKEN_ID, + 1, + &rust_biguint!(TOKEN_BALANCE), + Some(&DummyAttributes { dummy: 42 }), + ); +} + +#[test] +fn transfer_token_to_and_from_sov_ok() { + let mut bridge_setup = BridgeSetup::new(esdt_safe::contract_obj); + + let transfers = [ + TxTokenTransfer { + token_identifier: FUNGIBLE_TOKEN_ID.to_vec(), + nonce: 0, + value: rust_biguint!(1_000), + }, + TxTokenTransfer { + token_identifier: NFT_TOKEN_ID.to_vec(), + nonce: 1, + value: rust_biguint!(2_000), + }, + ]; + + let user_addr = bridge_setup.user.clone(); + let dest = bridge_setup.sov_dest_addr.clone(); + + bridge_setup + .b_mock + .execute_esdt_multi_transfer( + &bridge_setup.user, + &bridge_setup.bridge_wrapper, + &transfers, + |sc| { + sc.create_transaction(managed_address!(&dest), OptionalValue::None); + }, + ) + .assert_ok(); + + bridge_setup + .b_mock + .execute_tx( + &bridge_setup.owner, + &bridge_setup.bridge_wrapper, + &rust_biguint!(0), + |sc| { + let mut statuses = MultiValueEncoded::new(); + statuses.push(TransactionStatus::Executed); + + sc.set_transaction_batch_status( + 1, + BlsSignature::new_from_bytes(&DUMMY_SIG), + statuses, + ); + }, + ) + .assert_ok(); + + bridge_setup + .b_mock + .execute_tx( + &bridge_setup.owner, + &bridge_setup.bridge_wrapper, + &rust_biguint!(0), + |sc| { + let mut tokens = ManagedVec::new(); + tokens.push(EsdtTokenPayment::new( + managed_token_id!(FUNGIBLE_TOKEN_ID), + 0, + managed_biguint!(500), + )); + tokens.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + 1, + managed_biguint!(500), + )); + + let mut token_data = ManagedVec::new(); + token_data.push(StolenFromFrameworkEsdtTokenData::default()); + token_data.push(StolenFromFrameworkEsdtTokenData::default()); + + let mut transfers = MultiValueEncoded::new(); + transfers.push(Transaction { + block_nonce: 1, + nonce: 1, + from: managed_address!(&dest), + to: managed_address!(&user_addr), + tokens, + token_data, + opt_transfer_data: None, + is_refund_tx: false, + }); + + sc.batch_transfer_esdt_token( + 1, + BlsSignature::new_from_bytes(&DUMMY_SIG), + transfers, + ); + }, + ) + .assert_ok(); + + bridge_setup.b_mock.check_esdt_balance( + &bridge_setup.user, + FUNGIBLE_TOKEN_ID, + &rust_biguint!(TOKEN_BALANCE - 1_000 + 500), + ); + bridge_setup.b_mock.check_nft_balance( + &bridge_setup.user, + NFT_TOKEN_ID, + 1, + &rust_biguint!(TOKEN_BALANCE - 2_000 + 500), + Some(&DummyAttributes { dummy: 42 }), + ); +} + +#[test] +fn transfer_token_from_sov_no_roles_refund() { + let mut bridge_setup = BridgeSetup::new(esdt_safe::contract_obj); + let user_addr = bridge_setup.user.clone(); + let dest = bridge_setup.sov_dest_addr.clone(); + + bridge_setup + .b_mock + .execute_tx( + &bridge_setup.owner, + &bridge_setup.bridge_wrapper, + &rust_biguint!(0), + |sc| { + let mut tokens = ManagedVec::new(); + tokens.push(EsdtTokenPayment::new( + managed_token_id!(FUNGIBLE_TOKEN_ID), + 0, + managed_biguint!(500), + )); + tokens.push(EsdtTokenPayment::new( + managed_token_id!(NFT_TOKEN_ID), + 1, + managed_biguint!(500), + )); + + let mut token_data = ManagedVec::new(); + token_data.push(StolenFromFrameworkEsdtTokenData::default()); + token_data.push(StolenFromFrameworkEsdtTokenData::default()); + + let mut transfers = MultiValueEncoded::new(); + transfers.push(Transaction { + block_nonce: 1, + nonce: 1, + from: managed_address!(&dest), + to: managed_address!(&user_addr), + tokens, + token_data, + opt_transfer_data: None, + is_refund_tx: false, + }); + + sc.batch_transfer_esdt_token( + 1, + BlsSignature::new_from_bytes(&DUMMY_SIG), + transfers, + ); + }, + ) + .assert_ok(); + + // user received no tokens + bridge_setup.b_mock.check_esdt_balance( + &bridge_setup.user, + FUNGIBLE_TOKEN_ID, + &rust_biguint!(TOKEN_BALANCE), + ); + bridge_setup.b_mock.check_nft_balance( + &bridge_setup.user, + NFT_TOKEN_ID, + 1, + &rust_biguint!(TOKEN_BALANCE), + Some(&DummyAttributes { dummy: 42 }), + ); + + // set block nonce in the future so batch is "final" + bridge_setup.b_mock.set_block_nonce(20); + + bridge_setup + .b_mock + .execute_tx( + &bridge_setup.owner, + &bridge_setup.bridge_wrapper, + &rust_biguint!(0), + |sc| { + // transactions were converted into Elrond -> Sov for refunding + let opt_val = sc.get_current_tx_batch(); + assert!(opt_val.is_some()); + }, + ) + .assert_ok(); +} diff --git a/esdt-safe/wasm/src/lib.rs b/esdt-safe/wasm/src/lib.rs index a3062a38..0cdf2153 100644 --- a/esdt-safe/wasm/src/lib.rs +++ b/esdt-safe/wasm/src/lib.rs @@ -5,10 +5,10 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 28 +// Endpoints: 27 // Async Callback: 1 // Promise callbacks: 1 -// Total number of exported functions: 31 +// Total number of exported functions: 30 #![no_std] @@ -45,7 +45,6 @@ multiversx_sc_wasm_adapter::endpoints! { getBatchStatus => get_batch_status getFirstBatchId => first_batch_id getLastBatchId => last_batch_id - getSovereignTxGasLimit => sovereign_tx_gas_limit setMaxBridgedAmount => set_max_bridged_amount getMaxBridgedAmount => max_bridged_amount pause => pause_endpoint