-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: FastBridgeV2 + TokenZapV1 integration
- Loading branch information
1 parent
e76174f
commit ae4fe60
Showing
5 changed files
with
392 additions
and
2 deletions.
There are no files selected for viewing
119 changes: 119 additions & 0 deletions
119
packages/contracts-rfq/test/integration/FastBridgeV2.TokenZapV1.Dst.t.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.24; | ||
|
||
import {TokenZapV1IntegrationTest, VaultManyArguments, IFastBridge, IFastBridgeV2} from "./TokenZapV1.t.sol"; | ||
|
||
// solhint-disable func-name-mixedcase, ordering | ||
contract FastBridgeV2TokenZapV1DstTest is TokenZapV1IntegrationTest { | ||
event BridgeRelayed( | ||
bytes32 indexed transactionId, | ||
address indexed relayer, | ||
address indexed to, | ||
uint32 originChainId, | ||
address originToken, | ||
address destToken, | ||
uint256 originAmount, | ||
uint256 destAmount, | ||
uint256 chainGasAmount | ||
); | ||
|
||
function setUp() public virtual override { | ||
vm.chainId(DST_CHAIN_ID); | ||
super.setUp(); | ||
} | ||
|
||
function mintTokens() public virtual override { | ||
deal(relayer, DST_AMOUNT); | ||
dstToken.mint(relayer, DST_AMOUNT); | ||
vm.prank(relayer); | ||
dstToken.approve(address(fastBridge), type(uint256).max); | ||
} | ||
|
||
function relay( | ||
IFastBridge.BridgeParams memory params, | ||
IFastBridgeV2.BridgeParamsV2 memory paramsV2, | ||
bool isToken | ||
) | ||
public | ||
{ | ||
bytes memory encodedBridgeTx = encodeBridgeTx(params, paramsV2); | ||
vm.prank({msgSender: relayer, txOrigin: relayer}); | ||
fastBridge.relay{value: isToken ? paramsV2.zapNative : DST_AMOUNT}(encodedBridgeTx); | ||
} | ||
|
||
function expectEventBridgeRelayed( | ||
IFastBridge.BridgeParams memory params, | ||
IFastBridgeV2.BridgeParamsV2 memory paramsV2, | ||
bool isToken | ||
) | ||
public | ||
{ | ||
bytes32 txId = keccak256(encodeBridgeTx(params, paramsV2)); | ||
vm.expectEmit(address(fastBridge)); | ||
emit BridgeRelayed({ | ||
transactionId: txId, | ||
relayer: relayer, | ||
to: address(dstZap), | ||
originChainId: SRC_CHAIN_ID, | ||
originToken: isToken ? address(srcToken) : NATIVE_GAS_TOKEN, | ||
destToken: isToken ? address(dstToken) : NATIVE_GAS_TOKEN, | ||
originAmount: SRC_AMOUNT, | ||
destAmount: DST_AMOUNT, | ||
chainGasAmount: paramsV2.zapNative | ||
}); | ||
} | ||
|
||
function checkBalances(bool isToken) public view { | ||
if (isToken) { | ||
assertEq(dstToken.balanceOf(user), 0); | ||
assertEq(dstToken.balanceOf(relayer), 0); | ||
assertEq(dstToken.balanceOf(address(fastBridge)), 0); | ||
assertEq(dstToken.balanceOf(address(dstZap)), 0); | ||
assertEq(dstToken.balanceOf(address(dstVault)), DST_AMOUNT); | ||
assertEq(dstVault.balanceOf(user, address(dstToken)), DST_AMOUNT); | ||
} else { | ||
assertEq(address(user).balance, 0); | ||
assertEq(address(relayer).balance, 0); | ||
assertEq(address(fastBridge).balance, 0); | ||
assertEq(address(dstZap).balance, 0); | ||
assertEq(address(dstVault).balance, DST_AMOUNT); | ||
assertEq(dstVault.balanceOf(user, NATIVE_GAS_TOKEN), DST_AMOUNT); | ||
} | ||
} | ||
|
||
function test_relay_depositTokenParams() public { | ||
expectEventBridgeRelayed({params: tokenParams, paramsV2: depositTokenParams, isToken: true}); | ||
relay({params: tokenParams, paramsV2: depositTokenParams, isToken: true}); | ||
checkBalances({isToken: true}); | ||
} | ||
|
||
function test_relay_depositTokenWithZapNativeParams() public { | ||
expectEventBridgeRelayed({params: tokenParams, paramsV2: depositTokenWithZapNativeParams, isToken: true}); | ||
relay({params: tokenParams, paramsV2: depositTokenWithZapNativeParams, isToken: true}); | ||
checkBalances({isToken: true}); | ||
// Extra ETH will be also custodied by the Vault | ||
assertEq(address(dstVault).balance, ZAP_NATIVE); | ||
} | ||
|
||
function test_relay_depositTokenRevertParams_revert() public { | ||
vm.expectRevert(VaultManyArguments.VaultManyArguments__SomeError.selector); | ||
relay({params: tokenParams, paramsV2: depositTokenRevertParams, isToken: true}); | ||
} | ||
|
||
function test_relay_depositNativeParams() public { | ||
expectEventBridgeRelayed({params: nativeParams, paramsV2: depositNativeParams, isToken: false}); | ||
relay({params: nativeParams, paramsV2: depositNativeParams, isToken: false}); | ||
checkBalances({isToken: false}); | ||
} | ||
|
||
function test_relay_depositNativeNoAmountParams() public { | ||
expectEventBridgeRelayed({params: nativeParams, paramsV2: depositNativeNoAmountParams, isToken: false}); | ||
relay({params: nativeParams, paramsV2: depositNativeNoAmountParams, isToken: false}); | ||
checkBalances({isToken: false}); | ||
} | ||
|
||
function test_relay_depositNativeRevertParams_revert() public { | ||
vm.expectRevert(VaultManyArguments.VaultManyArguments__SomeError.selector); | ||
relay({params: nativeParams, paramsV2: depositNativeRevertParams, isToken: false}); | ||
} | ||
} |
111 changes: 111 additions & 0 deletions
111
packages/contracts-rfq/test/integration/FastBridgeV2.TokenZapV1.Src.t.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.24; | ||
|
||
import {TokenZapV1IntegrationTest, IFastBridge, IFastBridgeV2} from "./TokenZapV1.t.sol"; | ||
|
||
// solhint-disable func-name-mixedcase, ordering | ||
contract FastBridgeV2TokenZapV1SrcTest is TokenZapV1IntegrationTest { | ||
event BridgeRequested( | ||
bytes32 indexed transactionId, | ||
address indexed sender, | ||
bytes request, | ||
uint32 destChainId, | ||
address originToken, | ||
address destToken, | ||
uint256 originAmount, | ||
uint256 destAmount, | ||
bool sendChainGas | ||
); | ||
|
||
function setUp() public virtual override { | ||
vm.chainId(SRC_CHAIN_ID); | ||
super.setUp(); | ||
} | ||
|
||
function mintTokens() public virtual override { | ||
deal(user, SRC_AMOUNT); | ||
srcToken.mint(user, SRC_AMOUNT); | ||
vm.prank(user); | ||
srcToken.approve(address(fastBridge), type(uint256).max); | ||
} | ||
|
||
function bridge( | ||
IFastBridge.BridgeParams memory params, | ||
IFastBridgeV2.BridgeParamsV2 memory paramsV2, | ||
bool isToken | ||
) | ||
public | ||
{ | ||
vm.prank({msgSender: user, txOrigin: user}); | ||
fastBridge.bridge{value: isToken ? 0 : SRC_AMOUNT}(params, paramsV2); | ||
} | ||
|
||
function expectEventBridgeRequested( | ||
IFastBridge.BridgeParams memory params, | ||
IFastBridgeV2.BridgeParamsV2 memory paramsV2, | ||
bool isToken | ||
) | ||
public | ||
{ | ||
bytes memory encodedBridgeTx = encodeBridgeTx(params, paramsV2); | ||
bytes32 txId = keccak256(encodedBridgeTx); | ||
vm.expectEmit(address(fastBridge)); | ||
emit BridgeRequested({ | ||
transactionId: txId, | ||
sender: user, | ||
request: encodedBridgeTx, | ||
destChainId: DST_CHAIN_ID, | ||
originToken: isToken ? address(srcToken) : NATIVE_GAS_TOKEN, | ||
destToken: isToken ? address(dstToken) : NATIVE_GAS_TOKEN, | ||
originAmount: SRC_AMOUNT, | ||
destAmount: DST_AMOUNT, | ||
sendChainGas: paramsV2.zapNative > 0 | ||
}); | ||
} | ||
|
||
function checkBalances(bool isToken) public view { | ||
if (isToken) { | ||
assertEq(srcToken.balanceOf(user), 0); | ||
assertEq(srcToken.balanceOf(address(fastBridge)), SRC_AMOUNT); | ||
} else { | ||
assertEq(address(user).balance, 0); | ||
assertEq(address(fastBridge).balance, SRC_AMOUNT); | ||
} | ||
} | ||
|
||
function test_bridge_depositTokenParams() public { | ||
expectEventBridgeRequested({params: tokenParams, paramsV2: depositTokenParams, isToken: true}); | ||
bridge({params: tokenParams, paramsV2: depositTokenParams, isToken: true}); | ||
checkBalances({isToken: true}); | ||
} | ||
|
||
function test_bridge_depositTokenWithZapNativeParams() public { | ||
expectEventBridgeRequested({params: tokenParams, paramsV2: depositTokenWithZapNativeParams, isToken: true}); | ||
bridge({params: tokenParams, paramsV2: depositTokenWithZapNativeParams, isToken: true}); | ||
checkBalances({isToken: true}); | ||
} | ||
|
||
function test_bridge_depositTokenRevertParams() public { | ||
expectEventBridgeRequested({params: tokenParams, paramsV2: depositTokenRevertParams, isToken: true}); | ||
bridge({params: tokenParams, paramsV2: depositTokenRevertParams, isToken: true}); | ||
checkBalances({isToken: true}); | ||
} | ||
|
||
function test_bridge_depositNativeParams() public { | ||
expectEventBridgeRequested({params: nativeParams, paramsV2: depositNativeParams, isToken: false}); | ||
bridge({params: nativeParams, paramsV2: depositNativeParams, isToken: false}); | ||
checkBalances({isToken: false}); | ||
} | ||
|
||
function test_bridge_depositNativeNoAmountParams() public { | ||
expectEventBridgeRequested({params: nativeParams, paramsV2: depositNativeNoAmountParams, isToken: false}); | ||
bridge({params: nativeParams, paramsV2: depositNativeNoAmountParams, isToken: false}); | ||
checkBalances({isToken: false}); | ||
} | ||
|
||
function test_bridge_depositNativeRevertParams() public { | ||
expectEventBridgeRequested({params: nativeParams, paramsV2: depositNativeRevertParams, isToken: false}); | ||
bridge({params: nativeParams, paramsV2: depositNativeRevertParams, isToken: false}); | ||
checkBalances({isToken: false}); | ||
} | ||
} |
160 changes: 160 additions & 0 deletions
160
packages/contracts-rfq/test/integration/TokenZapV1.t.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.24; | ||
|
||
import {FastBridgeV2, IFastBridge, IFastBridgeV2} from "../../contracts/FastBridgeV2.sol"; | ||
import {BridgeTransactionV2Lib} from "../../contracts/libs/BridgeTransactionV2.sol"; | ||
import {ZapDataV1} from "../../contracts/libs/ZapDataV1.sol"; | ||
import {TokenZapV1} from "../../contracts/zaps/TokenZapV1.sol"; | ||
|
||
import {VaultManyArguments} from "../mocks/VaultManyArguments.sol"; | ||
import {MockERC20} from "../MockERC20.sol"; | ||
|
||
import {Test} from "forge-std/Test.sol"; | ||
|
||
// solhint-disable ordering | ||
abstract contract TokenZapV1IntegrationTest is Test { | ||
address internal constant NATIVE_GAS_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; | ||
|
||
uint32 internal constant SRC_CHAIN_ID = 1337; | ||
uint32 internal constant DST_CHAIN_ID = 7331; | ||
|
||
uint256 internal constant SRC_AMOUNT = 1 ether; | ||
uint256 internal constant DST_AMOUNT = 0.9999 ether; | ||
uint256 internal constant ZAP_NATIVE = 123_456; | ||
|
||
FastBridgeV2 internal fastBridge; | ||
TokenZapV1 internal dstZap; | ||
|
||
address internal user = makeAddr("User"); | ||
address internal relayer = makeAddr("Relayer"); | ||
|
||
MockERC20 internal srcToken; | ||
MockERC20 internal dstToken; | ||
|
||
VaultManyArguments internal dstVault; | ||
|
||
IFastBridge.BridgeParams internal tokenParams; | ||
IFastBridge.BridgeParams internal nativeParams; | ||
|
||
IFastBridgeV2.BridgeParamsV2 internal depositTokenParams; | ||
IFastBridgeV2.BridgeParamsV2 internal depositTokenWithZapNativeParams; | ||
IFastBridgeV2.BridgeParamsV2 internal depositTokenRevertParams; | ||
IFastBridgeV2.BridgeParamsV2 internal depositNativeParams; | ||
IFastBridgeV2.BridgeParamsV2 internal depositNativeNoAmountParams; | ||
IFastBridgeV2.BridgeParamsV2 internal depositNativeRevertParams; | ||
|
||
function setUp() public virtual { | ||
fastBridge = new FastBridgeV2(address(this)); | ||
fastBridge.grantRole(fastBridge.RELAYER_ROLE(), relayer); | ||
|
||
srcToken = new MockERC20("SRC", 18); | ||
dstToken = new MockERC20("DST", 18); | ||
|
||
dstZap = new TokenZapV1(); | ||
dstVault = new VaultManyArguments(); | ||
|
||
createFixtures(); | ||
mintTokens(); | ||
} | ||
|
||
function createFixtures() public virtual { | ||
tokenParams = IFastBridge.BridgeParams({ | ||
dstChainId: DST_CHAIN_ID, | ||
sender: user, | ||
to: address(dstZap), | ||
originToken: address(srcToken), | ||
destToken: address(dstToken), | ||
originAmount: SRC_AMOUNT, | ||
destAmount: DST_AMOUNT, | ||
sendChainGas: false, | ||
deadline: block.timestamp + 1 days | ||
}); | ||
nativeParams = IFastBridge.BridgeParams({ | ||
dstChainId: DST_CHAIN_ID, | ||
sender: user, | ||
to: address(dstZap), | ||
originToken: NATIVE_GAS_TOKEN, | ||
destToken: NATIVE_GAS_TOKEN, | ||
originAmount: SRC_AMOUNT, | ||
destAmount: DST_AMOUNT, | ||
sendChainGas: false, | ||
deadline: block.timestamp + 1 days | ||
}); | ||
// Deposit token | ||
bytes memory zapData = dstZap.encodeZapData({ | ||
target: address(dstVault), | ||
payload: getDepositPayload(address(dstToken)), | ||
amountPosition: 4 + 32 * 2 | ||
}); | ||
depositTokenParams.zapData = zapData; | ||
depositTokenWithZapNativeParams.zapData = zapData; | ||
depositTokenWithZapNativeParams.zapNative = ZAP_NATIVE; | ||
// Deposit native | ||
depositNativeParams.zapData = dstZap.encodeZapData({ | ||
target: address(dstVault), | ||
payload: getDepositPayload(NATIVE_GAS_TOKEN), | ||
amountPosition: 4 + 32 * 2 | ||
}); | ||
// Deposit no amount | ||
depositNativeNoAmountParams.zapData = dstZap.encodeZapData({ | ||
target: address(dstVault), | ||
payload: getDepositNoAmountPayload(), | ||
amountPosition: ZapDataV1.AMOUNT_NOT_PRESENT | ||
}); | ||
// Deposit revert | ||
depositTokenRevertParams.zapData = dstZap.encodeZapData({ | ||
target: address(dstVault), | ||
payload: getDepositRevertPayload(), | ||
amountPosition: ZapDataV1.AMOUNT_NOT_PRESENT | ||
}); | ||
depositNativeRevertParams.zapData = dstZap.encodeZapData({ | ||
target: address(dstVault), | ||
payload: getDepositRevertPayload(), | ||
amountPosition: ZapDataV1.AMOUNT_NOT_PRESENT | ||
}); | ||
} | ||
|
||
function mintTokens() public virtual; | ||
|
||
function encodeBridgeTx( | ||
IFastBridge.BridgeParams memory params, | ||
IFastBridgeV2.BridgeParamsV2 memory paramsV2 | ||
) | ||
public | ||
pure | ||
returns (bytes memory) | ||
{ | ||
IFastBridgeV2.BridgeTransactionV2 memory bridgeTx = IFastBridgeV2.BridgeTransactionV2({ | ||
originChainId: SRC_CHAIN_ID, | ||
destChainId: params.dstChainId, | ||
originSender: params.sender, | ||
destRecipient: params.to, | ||
originToken: params.originToken, | ||
destToken: params.destToken, | ||
originAmount: params.originAmount, | ||
destAmount: params.destAmount, | ||
// No protocol fees for the test | ||
originFeeAmount: 0, | ||
deadline: params.deadline, | ||
// Single tx is sent, so nonce is 0 | ||
nonce: 0, | ||
exclusivityRelayer: address(0), | ||
exclusivityEndTime: 0, | ||
zapNative: paramsV2.zapNative, | ||
zapData: paramsV2.zapData | ||
}); | ||
return BridgeTransactionV2Lib.encodeV2(bridgeTx); | ||
} | ||
|
||
function getDepositPayload(address token) public view returns (bytes memory) { | ||
return abi.encodeCall(dstVault.deposit, (token, abi.encode(token), DST_AMOUNT, user, abi.encode(user))); | ||
} | ||
|
||
function getDepositNoAmountPayload() public view returns (bytes memory) { | ||
return abi.encodeCall(dstVault.depositNoAmount, (user)); | ||
} | ||
|
||
function getDepositRevertPayload() public view returns (bytes memory) { | ||
return abi.encodeCall(dstVault.depositWithRevert, ()); | ||
} | ||
} |
Oops, something went wrong.