Skip to content

Commit

Permalink
Merge pull request #59 from bitfinity-network/additional_integration_…
Browse files Browse the repository at this point in the history
…tests_for_fees

[EPROD-883] Additional integration tests
  • Loading branch information
blutooth authored May 30, 2024
2 parents 002230a + d8eabad commit d1f75f9
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 47 deletions.
15 changes: 0 additions & 15 deletions solidity/src/BftBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -203,21 +203,6 @@ contract BFTBridge {
payable(minterCanisterAddress).transfer(msg.value);
}

// Transfer the given amount from native token deposit to the given address.
function withdrawNativeTokens(address payable to, uint256 amount) external returns (uint256 balance) {
address from = msg.sender;


balance = _userNativeDeposit[from];
require(balance >= amount, "Insufficient native token deposit balance");

balance -= amount;
_userNativeDeposit[from] = balance;

bool successful_send = to.send(amount);
require(successful_send, "Failed to send tokens");
}

// Remove approved SpenderIDs
function removeApprovedSenderIDs(bytes32[] calldata approvedSenderIDs) external {
for (uint i = 0; i < approvedSenderIDs.length; i++) {
Expand Down
5 changes: 3 additions & 2 deletions src/icrc2-minter/src/tasks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ impl BridgeTask {
let nonce = burnt_data.operation_id;

// If there is no fee payer, user should send mint tx by himself.
let should_send_mint_tx = burnt_data.fee_payer.is_some();
let fee_payer = burnt_data.fee_payer.unwrap_or_default();
let should_send_mint_tx = fee_payer != H160::zero();

let mint_order = MintOrder {
amount: burnt_data.amount,
Expand All @@ -196,7 +197,7 @@ impl BridgeTask {
decimals: burnt_data.decimals,
approve_spender: burnt_data.approve_spender,
approve_amount: burnt_data.approve_amount,
fee_payer: burnt_data.fee_payer.unwrap_or_default(),
fee_payer,
};

let signer = state.borrow().signer.get_transaction_signer();
Expand Down
2 changes: 1 addition & 1 deletion src/integration-tests/tests/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ pub trait TestContext {
))
})?;

if dbg!(receipt.status.unwrap().0.as_u64()) != 1 {
if receipt.status.unwrap().0.as_u64() != 1 {
let output = receipt
.output
.as_ref()
Expand Down
145 changes: 140 additions & 5 deletions src/integration-tests/tests/pocket_ic_integration_test/erc20_minter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,21 +193,18 @@ async fn test_external_bridging() {
let amount = 1000_u128;

// spender should deposit native tokens to bft bridge, to pay fee.
let expected_init_native_balance = 10_u64.pow(15);
let wrapped_evm_client = ctx.context.evm_client(ADMIN);
let bob_id = Id256::from_evm_address(&ctx.bob_address, CHAIN_ID as _);
let init_native_balance = ctx
.context
ctx.context
.native_token_deposit(
&wrapped_evm_client,
ctx.wrapped_bft_bridge.clone(),
&ctx.bob_wallet,
&[bob_id],
expected_init_native_balance.into(),
10_u64.pow(15).into(),
)
.await
.unwrap();
assert_eq!(init_native_balance, expected_init_native_balance.into());

let base_evm_client = EvmCanisterClient::new(
ctx.context
Expand Down Expand Up @@ -264,6 +261,99 @@ async fn test_external_bridging() {
.unwrap();

assert!(signed_order.is_none());
}

#[tokio::test]
async fn native_token_deposit_inrease_and_decrease() {
let ctx = ContextWithBridges::new().await;

// Approve ERC-20 transfer on behalf of some user in base EVM.
let alice_wallet = ctx.context.new_wallet(u128::MAX).await.unwrap();
let alice_address: H160 = alice_wallet.address().into();
let alice_id = Id256::from_evm_address(&alice_address, CHAIN_ID as _);
let amount = 1000_u128;
let wrapped_evm_client = ctx.context.evm_client(ADMIN);

let start_native_balance = ctx
.context
.native_token_deposit_balance(
&wrapped_evm_client,
ctx.wrapped_bft_bridge.clone(),
ctx.bob_address(),
)
.await;
assert_eq!(start_native_balance, U256::zero());

let init_bridge_canister_evm_balance = wrapped_evm_client
.eth_get_balance(ctx.erc20_minter_address.clone(), did::BlockNumber::Latest)
.await
.unwrap()
.unwrap();

// spender should deposit native tokens to bft bridge, to pay fee.
let native_balance_after_deposit = 10_u64.pow(15);
let bob_id = Id256::from_evm_address(&ctx.bob_address, CHAIN_ID as _);
let init_native_balance = ctx
.context
.native_token_deposit(
&wrapped_evm_client,
ctx.wrapped_bft_bridge.clone(),
&ctx.bob_wallet,
&[bob_id],
native_balance_after_deposit.into(),
)
.await
.unwrap();
assert_eq!(init_native_balance.0.as_u64(), native_balance_after_deposit);

let queried_balance = ctx
.context
.native_token_deposit_balance(
&wrapped_evm_client,
ctx.wrapped_bft_bridge.clone(),
ctx.bob_address(),
)
.await;
assert_eq!(queried_balance.0.as_u64(), native_balance_after_deposit);

let bridge_canister_evm_balance_after_deposit = wrapped_evm_client
.eth_get_balance(ctx.erc20_minter_address.clone(), did::BlockNumber::Latest)
.await
.unwrap()
.unwrap();

assert_eq!(
init_bridge_canister_evm_balance + init_native_balance.clone(),
bridge_canister_evm_balance_after_deposit
);

let base_evm_client = EvmCanisterClient::new(
ctx.context
.client(ctx.context.canisters().external_evm(), ADMIN),
);

// Perform an operation to pay a fee for it.
ctx.context
.burn_erc_20_tokens(
&base_evm_client,
&ctx.bob_wallet,
&ctx.base_token_address,
alice_id,
&ctx.base_bft_bridge,
amount,
)
.await
.unwrap();

// Advance time to perform two tasks in erc20-minter:
// 1. Minted event collection
// 2. Mint order removal
ctx.context.advance_time(Duration::from_secs(2)).await;
ctx.context.advance_time(Duration::from_secs(2)).await;
ctx.context.advance_time(Duration::from_secs(2)).await;
ctx.context.advance_time(Duration::from_secs(2)).await;
ctx.context.advance_time(Duration::from_secs(2)).await;
ctx.context.advance_time(Duration::from_secs(2)).await;

// Check fee charged
let native_balance_after_mint = ctx
Expand Down Expand Up @@ -324,6 +414,13 @@ async fn mint_should_fail_if_not_enough_tokens_on_fee_deposit() {
.unwrap();
assert_eq!(0, balance);

let wrapped_evm_client = ctx.context.evm_client(ADMIN);
let bridge_canister_evm_balance_after_failed_mint = wrapped_evm_client
.eth_get_balance(ctx.erc20_minter_address.clone(), did::BlockNumber::Latest)
.await
.unwrap()
.unwrap();

// Wait for mint order removal
ctx.context.advance_time(Duration::from_secs(2)).await;
ctx.context.advance_time(Duration::from_secs(2)).await;
Expand All @@ -345,6 +442,44 @@ async fn mint_should_fail_if_not_enough_tokens_on_fee_deposit() {
.unwrap();

assert!(signed_order.is_some());

ctx.context
.mint_erc_20_with_order(
&ctx.bob_wallet,
&ctx.wrapped_bft_bridge,
signed_order.unwrap(),
)
.await
.unwrap();

// Wait for mint tx finishing and mint oreder removing
ctx.context.advance_time(Duration::from_secs(2)).await;
ctx.context.advance_time(Duration::from_secs(2)).await;
ctx.context.advance_time(Duration::from_secs(2)).await;
ctx.context.advance_time(Duration::from_secs(2)).await;
ctx.context.advance_time(Duration::from_secs(2)).await;

// check mint order removed after successful mint
let signed_order = erc20_minter_client
.update::<_, Option<SignedMintOrder>>(
"get_mint_order",
(bob_address_id, base_token_id, burn_operation_id),
)
.await
.unwrap();
assert!(signed_order.is_none());

// Check bridge canister balance not changed after user's transaction.
let bridge_canister_evm_balance_after_user_mint = wrapped_evm_client
.eth_get_balance(ctx.erc20_minter_address.clone(), did::BlockNumber::Latest)
.await
.unwrap()
.unwrap();

assert_eq!(
bridge_canister_evm_balance_after_failed_mint,
bridge_canister_evm_balance_after_user_mint
);
}

#[tokio::test]
Expand Down
24 changes: 0 additions & 24 deletions src/minter-contract-utils/src/bft_bridge_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,30 +526,6 @@ pub static REMOVE_APPROVED_SPENDER_IDS: Lazy<Function> = Lazy::new(|| Function {
state_mutability: StateMutability::NonPayable,
});

#[allow(deprecated)] // need to initialize `constant` field
pub static NATIVE_TOKEN_WITHDRAW: Lazy<Function> = Lazy::new(|| Function {
name: "nativeTokenWithdraw".into(),
inputs: vec![
Param {
name: "to".into(),
kind: ParamType::Address,
internal_type: None,
},
Param {
name: "amount".into(),
kind: ParamType::Uint(256),
internal_type: None,
},
],
outputs: vec![Param {
name: "balance".into(),
kind: ParamType::Uint(256),
internal_type: None,
}],
constant: None,
state_mutability: StateMutability::NonPayable,
});

pub fn deploy_transaction(
sender: H160,
nonce: U256,
Expand Down

0 comments on commit d1f75f9

Please sign in to comment.