Skip to content

Commit

Permalink
Merge 129cde2 into edf99d3
Browse files Browse the repository at this point in the history
  • Loading branch information
ChiTimesChi authored Sep 27, 2024
2 parents edf99d3 + 129cde2 commit dc091ce
Show file tree
Hide file tree
Showing 8 changed files with 469 additions and 128 deletions.
9 changes: 2 additions & 7 deletions .github/workflows/solidity.yml
Original file line number Diff line number Diff line change
Expand Up @@ -264,15 +264,10 @@ jobs:
with:
version: nightly

# TODO: consider defining a package-specific script for this
- name: Run tests and generate gas report
working-directory: './packages/${{matrix.package}}'
# Excluding tests with reverts to get accurate average gas cost estimates
run: forge test --nmt "(fail|revert)" --gas-report > "../../gas-report-${{ matrix.package }}.ansi"
env:
# make fuzzing semi-deterministic to avoid noisy gas cost estimation
# due to non-deterministic fuzzing (but still use pseudo-random fuzzing seeds)
FOUNDRY_FUZZ_SEED: 0x${{ github.event.pull_request.base.sha || github.sha }}
# Run separate set of tests (no fuzzing) to get accurate average gas cost estimates
run: forge test --mc GasBenchmark --gas-report > "../../gas-report-${{ matrix.package }}.ansi"

- name: Compare gas reports
uses: Rubilmax/[email protected]
Expand Down
50 changes: 50 additions & 0 deletions packages/contracts-rfq/test/FastBridgeV2.Dst.Base.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {FastBridgeV2, FastBridgeV2Test, IFastBridge} from "./FastBridgeV2.t.sol";

// solhint-disable func-name-mixedcase, ordering
contract FastBridgeV2DstBaseTest is FastBridgeV2Test {
uint256 public constant LEFTOVER_BALANCE = 1 ether;

function setUp() public override {
vm.chainId(DST_CHAIN_ID);
super.setUp();
}

function deployFastBridge() public override returns (FastBridgeV2) {
return new FastBridgeV2(address(this));
}

function mintTokens() public virtual override {
dstToken.mint(address(relayerA), LEFTOVER_BALANCE + tokenParams.destAmount);
dstToken.mint(address(relayerB), LEFTOVER_BALANCE + tokenParams.destAmount);
deal(relayerA, LEFTOVER_BALANCE + ethParams.destAmount);
deal(relayerB, LEFTOVER_BALANCE + ethParams.destAmount);
vm.prank(relayerA);
dstToken.approve(address(fastBridge), type(uint256).max);
vm.prank(relayerB);
dstToken.approve(address(fastBridge), type(uint256).max);
}

// ══════════════════════════════════════════════════ HELPERS ══════════════════════════════════════════════════════

function relay(address caller, uint256 msgValue, IFastBridge.BridgeTransaction memory bridgeTx) public {
bytes memory request = abi.encode(bridgeTx);
vm.prank({msgSender: caller, txOrigin: caller});
fastBridge.relay{value: msgValue}(request);
}

function relayWithAddress(
address caller,
address relayer,
uint256 msgValue,
IFastBridge.BridgeTransaction memory bridgeTx
)
public
{
bytes memory request = abi.encode(bridgeTx);
vm.prank({msgSender: caller, txOrigin: caller});
fastBridge.relay{value: msgValue}(request, relayer);
}
}
41 changes: 2 additions & 39 deletions packages/contracts-rfq/test/FastBridgeV2.Dst.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ pragma solidity ^0.8.20;

import {ChainIncorrect, DeadlineExceeded, TransactionRelayed, ZeroAddress} from "../contracts/libs/Errors.sol";

import {FastBridgeV2, FastBridgeV2Test, IFastBridge} from "./FastBridgeV2.t.sol";
import {FastBridgeV2DstBaseTest, IFastBridge} from "./FastBridgeV2.Dst.Base.t.sol";

// solhint-disable func-name-mixedcase, ordering
contract FastBridgeV2DstTest is FastBridgeV2Test {
contract FastBridgeV2DstTest is FastBridgeV2DstBaseTest {
event BridgeRelayed(
bytes32 indexed transactionId,
address indexed relayer,
Expand All @@ -19,24 +19,6 @@ contract FastBridgeV2DstTest is FastBridgeV2Test {
uint256 chainGasAmount
);

uint256 public constant LEFTOVER_BALANCE = 1 ether;

function setUp() public override {
vm.chainId(DST_CHAIN_ID);
super.setUp();
}

function deployFastBridge() public override returns (FastBridgeV2) {
return new FastBridgeV2(address(this));
}

function mintTokens() public override {
dstToken.mint(address(relayerA), LEFTOVER_BALANCE + tokenParams.destAmount);
deal(relayerB, LEFTOVER_BALANCE + ethParams.destAmount);
vm.prank(relayerA);
dstToken.approve(address(fastBridge), type(uint256).max);
}

function expectBridgeRelayed(IFastBridge.BridgeTransaction memory bridgeTx, bytes32 txId, address relayer) public {
vm.expectEmit(address(fastBridge));
emit BridgeRelayed({
Expand All @@ -52,25 +34,6 @@ contract FastBridgeV2DstTest is FastBridgeV2Test {
});
}

function relay(address caller, uint256 msgValue, IFastBridge.BridgeTransaction memory bridgeTx) public {
bytes memory request = abi.encode(bridgeTx);
vm.prank(caller);
fastBridge.relay{value: msgValue}(request);
}

function relayWithAddress(
address caller,
address relayer,
uint256 msgValue,
IFastBridge.BridgeTransaction memory bridgeTx
)
public
{
bytes memory request = abi.encode(bridgeTx);
vm.prank(caller);
fastBridge.relay{value: msgValue}(request, relayer);
}

/// @notice RelayerA completes the ERC20 bridge request
function test_relay_token() public {
bytes32 txId = getTxId(tokenTx);
Expand Down
65 changes: 65 additions & 0 deletions packages/contracts-rfq/test/FastBridgeV2.GasBench.Dst.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {FastBridgeV2DstBaseTest} from "./FastBridgeV2.Dst.Base.t.sol";

// solhint-disable func-name-mixedcase, ordering
/// @notice This test is used to estimate the gas cost of FastBridgeV2 destination chain functions.
/// Very little state checks are performed, make sure to do full coverage in different tests.
contract FastBridgeV2DstGasBenchmarkTest is FastBridgeV2DstBaseTest {
uint256 public constant INITIAL_USER_BALANCE = 100 ether;

function mintTokens() public virtual override {
super.mintTokens();
deal(userB, INITIAL_USER_BALANCE);
dstToken.mint(userB, INITIAL_USER_BALANCE);
}

// ═══════════════════════════════════════════════════ TOKEN ═══════════════════════════════════════════════════════

function test_relay_token() public {
bytes32 txId = getTxId(tokenTx);
relay({caller: relayerA, msgValue: 0, bridgeTx: tokenTx});
(uint256 blockNumber, uint256 blockTimestamp, address relayer) = fastBridge.bridgeRelayDetails(txId);
assertEq(blockNumber, block.number);
assertEq(blockTimestamp, block.timestamp);
assertEq(relayer, relayerA);
assertEq(dstToken.balanceOf(userB), INITIAL_USER_BALANCE + tokenParams.destAmount);
assertEq(dstToken.balanceOf(relayerA), LEFTOVER_BALANCE);
}

function test_relay_token_withRelayerAddress() public {
bytes32 txId = getTxId(tokenTx);
relayWithAddress({caller: relayerB, relayer: relayerA, msgValue: 0, bridgeTx: tokenTx});
(uint256 blockNumber, uint256 blockTimestamp, address relayer) = fastBridge.bridgeRelayDetails(txId);
assertEq(blockNumber, block.number);
assertEq(blockTimestamp, block.timestamp);
assertEq(relayer, relayerA);
assertEq(dstToken.balanceOf(userB), INITIAL_USER_BALANCE + tokenParams.destAmount);
assertEq(dstToken.balanceOf(relayerB), LEFTOVER_BALANCE);
}

// ════════════════════════════════════════════════════ ETH ════════════════════════════════════════════════════════

function test_relay_eth() public {
bytes32 txId = getTxId(ethTx);
relay({caller: relayerA, msgValue: ethParams.destAmount, bridgeTx: ethTx});
(uint256 blockNumber, uint256 blockTimestamp, address relayer) = fastBridge.bridgeRelayDetails(txId);
assertEq(blockNumber, block.number);
assertEq(blockTimestamp, block.timestamp);
assertEq(relayer, relayerA);
assertEq(address(userB).balance, INITIAL_USER_BALANCE + ethParams.destAmount);
assertEq(address(relayerA).balance, LEFTOVER_BALANCE);
}

function test_relay_eth_withRelayerAddress() public {
bytes32 txId = getTxId(ethTx);
relayWithAddress({caller: relayerB, relayer: relayerA, msgValue: ethParams.destAmount, bridgeTx: ethTx});
(uint256 blockNumber, uint256 blockTimestamp, address relayer) = fastBridge.bridgeRelayDetails(txId);
assertEq(blockNumber, block.number);
assertEq(blockTimestamp, block.timestamp);
assertEq(relayer, relayerA);
assertEq(address(userB).balance, INITIAL_USER_BALANCE + ethParams.destAmount);
assertEq(address(relayerB).balance, LEFTOVER_BALANCE);
}
}
36 changes: 36 additions & 0 deletions packages/contracts-rfq/test/FastBridgeV2.GasBench.Src.PFees.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {FastBridgeV2GasBenchmarkSrcTest} from "./FastBridgeV2.GasBench.Src.t.sol";

// solhint-disable func-name-mixedcase, ordering
contract FastBridgeV2GasBenchmarkSrcProtocolFeesTest is FastBridgeV2GasBenchmarkSrcTest {
function configureFastBridge() public virtual override {
super.configureFastBridge();
fastBridge.grantRole(fastBridge.GOVERNOR_ROLE(), address(this));
fastBridge.setProtocolFeeRate(1e4); // 1%
}

function createFixtures() public virtual override {
super.createFixtures();
tokenTx.originFeeAmount = 0.01e6;
tokenTx.originAmount = 0.99e6;
tokenTx.destAmount = 0.98e6;
tokenParams.destAmount = 0.98e6;
ethTx.originFeeAmount = 0.01 ether;
ethTx.originAmount = 0.99 ether;
ethTx.destAmount = 0.98 ether;
ethParams.destAmount = 0.98 ether;

// Copy txs to bridged and proven with different nonce
bridgedTokenTx = tokenTx;
provenTokenTx = tokenTx;
bridgedEthTx = ethTx;
provenEthTx = ethTx;

bridgedTokenTx.nonce = 0;
bridgedEthTx.nonce = 1;
provenTokenTx.nonce = 2;
provenEthTx.nonce = 3;
}
}
Loading

0 comments on commit dc091ce

Please sign in to comment.