chore: resolve merge conflicts
This commit is contained in:
@@ -78,6 +78,7 @@ contract Constants is Test, BaseConstants {
|
||||
|
||||
// Uniswap v3
|
||||
address DAI_WETH_USV3 = 0xC2e9F25Be6257c210d7Adf0D4Cd6E3E881ba25f8;
|
||||
address DAI_USDT_USV3 = 0x48DA0965ab2d2cbf1C17C09cFB5Cbe67Ad5B1406;
|
||||
address USDC_WETH_USV3 = 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640; // 0.05% fee
|
||||
address USDC_WETH_USV3_2 = 0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8; // 0.3% fee
|
||||
|
||||
|
||||
@@ -96,7 +96,6 @@ contract TychoRouterTest is TychoRouterTestSetup {
|
||||
}
|
||||
|
||||
vm.startPrank(FUND_RESCUER);
|
||||
|
||||
tychoRouter.withdraw(tokens, FUND_RESCUER);
|
||||
|
||||
// Check balances after withdrawing
|
||||
|
||||
@@ -493,6 +493,27 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
|
||||
assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0);
|
||||
}
|
||||
|
||||
function testSequentialSwapWithUnwrapIntegration() public {
|
||||
// Performs a sequential swap from USDC to ETH through WBTC using USV2 pools and unwrapping in
|
||||
// the end
|
||||
deal(USDC_ADDR, ALICE, 3_000_000_000);
|
||||
uint256 balanceBefore = ALICE.balance;
|
||||
|
||||
// Approve permit2
|
||||
vm.startPrank(ALICE);
|
||||
IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max);
|
||||
bytes memory callData =
|
||||
loadCallDataFromFile("test_sequential_swap_strategy_encoder_unwrap");
|
||||
(bool success,) = tychoRouterAddr.call(callData);
|
||||
|
||||
vm.stopPrank();
|
||||
|
||||
uint256 balanceAfter = ALICE.balance;
|
||||
|
||||
assertTrue(success, "Call Failed");
|
||||
assertEq(balanceAfter - balanceBefore, 1404194006633772805);
|
||||
}
|
||||
|
||||
function testUSV3BebopIntegration() public {
|
||||
// Performs a sequential swap from WETH to ONDO through USDC using USV3 and Bebop RFQ
|
||||
//
|
||||
|
||||
@@ -116,6 +116,7 @@ contract TychoRouterTestSetup is Constants, Permit2TestHelper, TestUtils {
|
||||
bytes32 initCodePancakeV3 = PANCAKEV3_POOL_CODE_INIT_HASH;
|
||||
address poolManagerAddress = 0x000000000004444c5dc75cB358380D2e3dE08A90;
|
||||
address ekuboCore = 0xe0e0e08A6A4b9Dc7bD67BCB7aadE5cF48157d444;
|
||||
address ekuboMevResist = 0x553a2EFc570c9e104942cEC6aC1c18118e54C091;
|
||||
|
||||
IPoolManager poolManager = IPoolManager(poolManagerAddress);
|
||||
usv2Executor =
|
||||
@@ -127,7 +128,8 @@ contract TychoRouterTestSetup is Constants, Permit2TestHelper, TestUtils {
|
||||
factoryPancakeV3, initCodePancakeV3, PERMIT2_ADDRESS
|
||||
);
|
||||
balancerv2Executor = new BalancerV2Executor(PERMIT2_ADDRESS);
|
||||
ekuboExecutor = new EkuboExecutor(ekuboCore, PERMIT2_ADDRESS);
|
||||
ekuboExecutor =
|
||||
new EkuboExecutor(ekuboCore, ekuboMevResist, PERMIT2_ADDRESS);
|
||||
curveExecutor = new CurveExecutor(ETH_ADDR_FOR_CURVE, PERMIT2_ADDRESS);
|
||||
maverickv2Executor =
|
||||
new MaverickV2Executor(MAVERICK_V2_FACTORY, PERMIT2_ADDRESS);
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -19,22 +19,29 @@ contract EkuboExecutorTest is Constants, TestUtils {
|
||||
IERC20 USDT = IERC20(USDT_ADDR);
|
||||
|
||||
address constant CORE_ADDRESS = 0xe0e0e08A6A4b9Dc7bD67BCB7aadE5cF48157d444;
|
||||
address constant MEV_RESIST_ADDRESS =
|
||||
0x553a2EFc570c9e104942cEC6aC1c18118e54C091;
|
||||
|
||||
bytes32 constant ORACLE_CONFIG =
|
||||
0x51d02a5948496a67827242eabc5725531342527c000000000000000000000000;
|
||||
|
||||
function setUp() public {
|
||||
vm.createSelectFork(vm.rpcUrl("mainnet"), 22082754);
|
||||
// 0.01% fee and 0.02% tick spacing
|
||||
bytes32 constant MEV_RESIST_POOL_CONFIG =
|
||||
0x553a2EFc570c9e104942cEC6aC1c18118e54C09100068db8bac710cb000000c8;
|
||||
|
||||
modifier setUpFork(uint256 blockNumber) {
|
||||
vm.createSelectFork(vm.rpcUrl("mainnet"), blockNumber);
|
||||
|
||||
deployCodeTo(
|
||||
"executors/EkuboExecutor.sol",
|
||||
abi.encode(CORE_ADDRESS, PERMIT2_ADDRESS),
|
||||
abi.encode(CORE_ADDRESS, MEV_RESIST_ADDRESS, PERMIT2_ADDRESS),
|
||||
EXECUTOR_ADDRESS
|
||||
);
|
||||
executor = EkuboExecutor(payable(EXECUTOR_ADDRESS));
|
||||
_;
|
||||
}
|
||||
|
||||
function testSingleSwapEth() public {
|
||||
function testSingleSwapEth() public setUpFork(22722989) {
|
||||
uint256 amountIn = 1 ether;
|
||||
|
||||
deal(address(executor), amountIn);
|
||||
@@ -71,7 +78,7 @@ contract EkuboExecutorTest is Constants, TestUtils {
|
||||
);
|
||||
}
|
||||
|
||||
function testSingleSwapERC20() public {
|
||||
function testSingleSwapERC20() public setUpFork(22722989) {
|
||||
uint256 amountIn = 1_000_000_000;
|
||||
|
||||
deal(USDC_ADDR, address(executor), amountIn);
|
||||
@@ -108,6 +115,43 @@ contract EkuboExecutorTest is Constants, TestUtils {
|
||||
);
|
||||
}
|
||||
|
||||
function testMevResist() public setUpFork(22722989) {
|
||||
uint256 amountIn = 1_000_000_000;
|
||||
|
||||
deal(USDC_ADDR, address(executor), amountIn);
|
||||
|
||||
uint256 usdcBalanceBeforeCore = USDC.balanceOf(CORE_ADDRESS);
|
||||
uint256 usdcBalanceBeforeExecutor = USDC.balanceOf(address(executor));
|
||||
|
||||
uint256 ethBalanceBeforeCore = CORE_ADDRESS.balance;
|
||||
uint256 ethBalanceBeforeExecutor = address(executor).balance;
|
||||
|
||||
bytes memory data = abi.encodePacked(
|
||||
uint8(RestrictTransferFrom.TransferType.Transfer), // transferNeeded (transfer from executor to core)
|
||||
address(executor), // receiver
|
||||
USDC_ADDR, // tokenIn
|
||||
NATIVE_TOKEN_ADDRESS, // tokenOut
|
||||
MEV_RESIST_POOL_CONFIG // config
|
||||
);
|
||||
|
||||
uint256 gasBefore = gasleft();
|
||||
uint256 amountOut = executor.swap(amountIn, data);
|
||||
console.log(gasBefore - gasleft());
|
||||
|
||||
console.log(amountOut);
|
||||
|
||||
assertEq(USDC.balanceOf(CORE_ADDRESS), usdcBalanceBeforeCore + amountIn);
|
||||
assertEq(
|
||||
USDC.balanceOf(address(executor)),
|
||||
usdcBalanceBeforeExecutor - amountIn
|
||||
);
|
||||
|
||||
assertEq(CORE_ADDRESS.balance, ethBalanceBeforeCore - amountOut);
|
||||
assertEq(
|
||||
address(executor).balance, ethBalanceBeforeExecutor + amountOut
|
||||
);
|
||||
}
|
||||
|
||||
// Expects input that encodes the same test case as swap_encoder::tests::ekubo::test_encode_swap_multi
|
||||
function multiHopSwap(bytes memory data) internal {
|
||||
uint256 amountIn = 1 ether;
|
||||
@@ -139,7 +183,7 @@ contract EkuboExecutorTest is Constants, TestUtils {
|
||||
}
|
||||
|
||||
// Same test case as in swap_encoder::tests::ekubo::test_encode_swap_multi
|
||||
function testMultiHopSwap() public {
|
||||
function testMultiHopSwap() public setUpFork(22082754) {
|
||||
bytes memory data = abi.encodePacked(
|
||||
uint8(RestrictTransferFrom.TransferType.Transfer), // transferNeeded (transfer from executor to core)
|
||||
address(executor), // receiver
|
||||
@@ -155,7 +199,7 @@ contract EkuboExecutorTest is Constants, TestUtils {
|
||||
}
|
||||
|
||||
// Data is generated by test case in swap_encoder::tests::ekubo::test_encode_swap_multi
|
||||
function testMultiHopSwapIntegration() public {
|
||||
function testMultiHopSwapIntegration() public setUpFork(22082754) {
|
||||
multiHopSwap(loadCallDataFromFile("test_ekubo_encode_swap_multi"));
|
||||
}
|
||||
}
|
||||
|
||||
302
foundry/test/uniswap_x/UniswapXFiller.t.sol
Normal file
302
foundry/test/uniswap_x/UniswapXFiller.t.sol
Normal file
@@ -0,0 +1,302 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
pragma solidity ^0.8.26;
|
||||
|
||||
import "forge-std/Test.sol";
|
||||
import "@src/uniswap_x/UniswapXFiller.sol";
|
||||
import "../TychoRouterTestSetup.sol";
|
||||
|
||||
contract UniswapXFillerTest is Test, TychoRouterTestSetup {
|
||||
address EXECUTOR = address(0xCe79b081c0c924cb67848723ed3057234d10FC6b);
|
||||
address REACTOR = address(0x00000011F84B9aa48e5f8aA8B9897600006289Be);
|
||||
|
||||
UniswapXFiller filler;
|
||||
address fillerAddr;
|
||||
|
||||
event CallbackVerifierSet(address indexed callbackVerifier);
|
||||
event Withdrawal(
|
||||
address indexed token, uint256 amount, address indexed receiver
|
||||
);
|
||||
|
||||
function getForkBlock() public pure override returns (uint256) {
|
||||
return 22880493;
|
||||
}
|
||||
|
||||
function fillerSetup() public {
|
||||
vm.startPrank(ADMIN);
|
||||
filler = new UniswapXFiller(tychoRouterAddr, REACTOR, address(0));
|
||||
fillerAddr = address(filler);
|
||||
filler.grantRole(keccak256("EXECUTOR_ROLE"), EXECUTOR);
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
function testTychoAddressZeroTychoRouter() public {
|
||||
vm.expectRevert(UniswapXFiller__AddressZero.selector);
|
||||
filler = new UniswapXFiller(address(0), REACTOR, address(0));
|
||||
}
|
||||
|
||||
function testTychoAddressZeroReactor() public {
|
||||
vm.expectRevert(UniswapXFiller__AddressZero.selector);
|
||||
filler = new UniswapXFiller(tychoRouterAddr, address(0), address(0));
|
||||
}
|
||||
|
||||
function testCallback() public {
|
||||
fillerSetup();
|
||||
uint256 amountIn = 10 ** 18;
|
||||
uint256 amountOut = 1847751195973566072891;
|
||||
bool zeroForOne = false;
|
||||
bytes memory protocolData = abi.encodePacked(
|
||||
WETH_ADDR,
|
||||
WETH_DAI_POOL,
|
||||
address(filler),
|
||||
zeroForOne,
|
||||
RestrictTransferFrom.TransferType.TransferFrom
|
||||
);
|
||||
|
||||
bytes memory swap =
|
||||
encodeSingleSwap(address(usv2Executor), protocolData);
|
||||
|
||||
bytes memory tychoRouterData = abi.encodeWithSelector(
|
||||
tychoRouter.singleSwap.selector,
|
||||
amountIn,
|
||||
WETH_ADDR,
|
||||
DAI_ADDR,
|
||||
2008817438608734439722,
|
||||
false,
|
||||
false,
|
||||
address(filler),
|
||||
true,
|
||||
swap
|
||||
);
|
||||
|
||||
bytes memory callbackData =
|
||||
abi.encodePacked(true, true, tychoRouterData);
|
||||
|
||||
deal(WETH_ADDR, address(filler), amountIn);
|
||||
|
||||
ResolvedOrder[] memory orders = new ResolvedOrder[](1);
|
||||
OutputToken[] memory outputs = new OutputToken[](1);
|
||||
outputs[0] = OutputToken({
|
||||
token: address(DAI_ADDR),
|
||||
amount: 1847751195973566072891,
|
||||
recipient: BOB
|
||||
});
|
||||
// Irrelevant fields for this test - we only need token output
|
||||
// info for the sake of testing.
|
||||
orders[0] = ResolvedOrder({
|
||||
info: OrderInfo({
|
||||
reactor: address(0),
|
||||
swapper: address(0),
|
||||
nonce: 0,
|
||||
deadline: 0,
|
||||
additionalValidationContract: address(0),
|
||||
additionalValidationData: ""
|
||||
}),
|
||||
input: InputToken({
|
||||
token: address(WETH_ADDR),
|
||||
amount: amountIn,
|
||||
maxAmount: amountIn
|
||||
}),
|
||||
outputs: outputs,
|
||||
sig: "",
|
||||
hash: ""
|
||||
});
|
||||
|
||||
vm.startPrank(REACTOR);
|
||||
filler.reactorCallback(orders, callbackData);
|
||||
vm.stopPrank();
|
||||
|
||||
// Check that the funds are in the filler at the end of the function call
|
||||
uint256 finalBalance = IERC20(DAI_ADDR).balanceOf(address(filler));
|
||||
assertGe(finalBalance, amountOut);
|
||||
|
||||
// Check that the proper approval was set
|
||||
vm.startPrank(REACTOR);
|
||||
IERC20(DAI_ADDR).transferFrom(address(filler), BOB, amountOut);
|
||||
vm.stopPrank();
|
||||
assertGe(IERC20(DAI_ADDR).balanceOf(BOB), amountOut);
|
||||
}
|
||||
|
||||
function testExecuteIntegration() public {
|
||||
fillerSetup();
|
||||
|
||||
// Set to time with no more penalty for not being exclusive filler
|
||||
vm.warp(1752050415);
|
||||
|
||||
deal(
|
||||
DAI_ADDR,
|
||||
address(0xD213e6F6dCB2DBaC03FA28b893F6dA1BD822e852),
|
||||
2000 ether
|
||||
);
|
||||
|
||||
uint256 amountIn = 2000000000000000000000;
|
||||
|
||||
vm.startPrank(address(0xD213e6F6dCB2DBaC03FA28b893F6dA1BD822e852));
|
||||
// Approve Permit2
|
||||
IERC20(DAI_ADDR).approve(
|
||||
address(0x000000000022D473030F116dDEE9F6B43aC78BA3), amountIn
|
||||
);
|
||||
vm.stopPrank();
|
||||
|
||||
// Tx 0x005d7b150017ba1b59d2f99395ccae7bda9b739938ade4e509817e32760aaf9d
|
||||
// Calldata generated using rust test `test_sequential_swap_usx`
|
||||
|
||||
SignedOrder memory order = SignedOrder({
|
||||
order: hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001000000000000000000000000004449cd34d1eb1fedcf02a1be3834ffde8e6a61800000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000006c6b935b8bbd40000000000000000000000000000000000000000000000000006c6b935b8bbd40000000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000011f84b9aa48e5f8aa8b9897600006289be000000000000000000000000d213e6f6dcb2dbac03fa28b893f6da1bd822e8520468320351debb1ddbfb032a239d699e3d54e3ce2b6e1037cd836a784c80b60100000000000000000000000000000000000000000000000000000000686e2bf9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec70000000000000000000000000000000000000000000000000000000076f9f4870000000000000000000000000000000000000000000000000000000076566300000000000000000000000000d213e6f6dcb2dbac03fa28b893f6da1bd822e85200000000000000000000000000000000000000000000000000000000686e2aee00000000000000000000000000000000000000000000000000000000686e2b2a000000000000000000000000ce79b081c0c924cb67848723ed3057234d10fc6b0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000007727b5f40000000000000000000000000000000000000000000000000000000000000041a2d261cd4c8930428260f18b55e3036024bac68d58cb2ee6161e6395b0984b827104158713d44ddc4e14d852b48d93d95a4e60b8d5be1ef431c1e82d2f76a4111b00000000000000000000000000000000000000000000000000000000000000",
|
||||
sig: hex"f4cc5734820e4ee08519045c83a25b75687756053b3d6c0fda2141380dfa6ef17b40f64d9279f237e96982c6ba53a202e01a4358fd66e027c9bdf200d5626f441c"
|
||||
});
|
||||
|
||||
bytes memory callbackData =
|
||||
loadCallDataFromFile("test_sequential_swap_usx");
|
||||
|
||||
vm.startPrank(EXECUTOR);
|
||||
filler.execute(order, callbackData);
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
function testExecute() public {
|
||||
fillerSetup();
|
||||
|
||||
// Set to time with no more penalty for not being exclusive filler
|
||||
vm.warp(1752050415);
|
||||
|
||||
// tx: 0x005d7b150017ba1b59d2f99395ccae7bda9b739938ade4e509817e32760aaf9d
|
||||
// DAI ──> USDT
|
||||
SignedOrder memory order = SignedOrder({
|
||||
order: hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001000000000000000000000000004449cd34d1eb1fedcf02a1be3834ffde8e6a61800000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000006c6b935b8bbd40000000000000000000000000000000000000000000000000006c6b935b8bbd40000000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000011f84b9aa48e5f8aa8b9897600006289be000000000000000000000000d213e6f6dcb2dbac03fa28b893f6da1bd822e8520468320351debb1ddbfb032a239d699e3d54e3ce2b6e1037cd836a784c80b60100000000000000000000000000000000000000000000000000000000686e2bf9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec70000000000000000000000000000000000000000000000000000000076f9f4870000000000000000000000000000000000000000000000000000000076566300000000000000000000000000d213e6f6dcb2dbac03fa28b893f6da1bd822e85200000000000000000000000000000000000000000000000000000000686e2aee00000000000000000000000000000000000000000000000000000000686e2b2a000000000000000000000000ce79b081c0c924cb67848723ed3057234d10fc6b0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000007727b5f40000000000000000000000000000000000000000000000000000000000000041a2d261cd4c8930428260f18b55e3036024bac68d58cb2ee6161e6395b0984b827104158713d44ddc4e14d852b48d93d95a4e60b8d5be1ef431c1e82d2f76a4111b00000000000000000000000000000000000000000000000000000000000000",
|
||||
sig: hex"f4cc5734820e4ee08519045c83a25b75687756053b3d6c0fda2141380dfa6ef17b40f64d9279f237e96982c6ba53a202e01a4358fd66e027c9bdf200d5626f441c"
|
||||
});
|
||||
|
||||
uint256 amountIn = 2000000000000000000000;
|
||||
bool zeroForOne = true;
|
||||
uint24 fee = 100;
|
||||
bytes memory protocolData = abi.encodePacked(
|
||||
DAI_ADDR,
|
||||
USDT_ADDR,
|
||||
fee,
|
||||
fillerAddr,
|
||||
DAI_USDT_USV3,
|
||||
zeroForOne,
|
||||
RestrictTransferFrom.TransferType.TransferFrom
|
||||
);
|
||||
|
||||
bytes memory swap =
|
||||
encodeSingleSwap(address(usv3Executor), protocolData);
|
||||
|
||||
bytes memory tychoRouterData = abi.encodeWithSelector(
|
||||
tychoRouter.singleSwap.selector,
|
||||
amountIn,
|
||||
DAI_ADDR,
|
||||
USDT_ADDR,
|
||||
1,
|
||||
false,
|
||||
false,
|
||||
fillerAddr,
|
||||
true,
|
||||
swap
|
||||
);
|
||||
|
||||
bytes memory callbackData = abi.encodePacked(
|
||||
true, // tokenIn approval needed
|
||||
true, // tokenOut approval needed
|
||||
tychoRouterData
|
||||
);
|
||||
|
||||
vm.startPrank(address(filler));
|
||||
IERC20(WBTC_ADDR).approve(tychoRouterAddr, amountIn);
|
||||
vm.stopPrank();
|
||||
|
||||
vm.startPrank(EXECUTOR);
|
||||
filler.execute(order, callbackData);
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
function testWithdrawNative() public {
|
||||
fillerSetup();
|
||||
vm.startPrank(ADMIN);
|
||||
// Send 100 ether to filler
|
||||
assertEq(fillerAddr.balance, 0);
|
||||
assertEq(ADMIN.balance, 0);
|
||||
vm.deal(fillerAddr, 100 ether);
|
||||
vm.expectEmit();
|
||||
emit Withdrawal(address(0), 100 ether, ADMIN);
|
||||
filler.withdrawNative(ADMIN);
|
||||
assertEq(fillerAddr.balance, 0);
|
||||
assertEq(ADMIN.balance, 100 ether);
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
function testWithdrawNativeAddressZero() public {
|
||||
fillerSetup();
|
||||
vm.deal(fillerAddr, 100 ether);
|
||||
vm.startPrank(ADMIN);
|
||||
vm.expectRevert(UniswapXFiller__AddressZero.selector);
|
||||
filler.withdrawNative(address(0));
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
function testWithdrawNativeMissingRole() public {
|
||||
fillerSetup();
|
||||
vm.deal(fillerAddr, 100 ether);
|
||||
// Not role ADMIN
|
||||
vm.startPrank(BOB);
|
||||
vm.expectRevert();
|
||||
filler.withdrawNative(ADMIN);
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
function testWithdrawERC20Tokens() public {
|
||||
fillerSetup();
|
||||
|
||||
IERC20[] memory tokens = new IERC20[](2);
|
||||
tokens[0] = IERC20(WETH_ADDR);
|
||||
tokens[1] = IERC20(USDC_ADDR);
|
||||
for (uint256 i = 0; i < tokens.length; i++) {
|
||||
deal(address(tokens[i]), fillerAddr, 100 ether);
|
||||
}
|
||||
|
||||
vm.startPrank(ADMIN);
|
||||
filler.withdraw(tokens, ADMIN);
|
||||
|
||||
// Check balances after withdrawing
|
||||
for (uint256 i = 0; i < tokens.length; i++) {
|
||||
// slither-disable-next-line calls-loop
|
||||
assertEq(tokens[i].balanceOf(fillerAddr), 0);
|
||||
// slither-disable-next-line calls-loop
|
||||
assertEq(tokens[i].balanceOf(ADMIN), 100 ether);
|
||||
}
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
function testWithdrawERC20TokensAddressZero() public {
|
||||
fillerSetup();
|
||||
|
||||
IERC20[] memory tokens = new IERC20[](2);
|
||||
tokens[0] = IERC20(WETH_ADDR);
|
||||
tokens[1] = IERC20(USDC_ADDR);
|
||||
for (uint256 i = 0; i < tokens.length; i++) {
|
||||
deal(address(tokens[i]), fillerAddr, 100 ether);
|
||||
}
|
||||
|
||||
vm.startPrank(ADMIN);
|
||||
vm.expectRevert(UniswapXFiller__AddressZero.selector);
|
||||
filler.withdraw(tokens, address(0));
|
||||
vm.stopPrank();
|
||||
}
|
||||
|
||||
function testWithdrawERC20TokensAddressMissingRole() public {
|
||||
fillerSetup();
|
||||
|
||||
IERC20[] memory tokens = new IERC20[](2);
|
||||
tokens[0] = IERC20(WETH_ADDR);
|
||||
tokens[1] = IERC20(USDC_ADDR);
|
||||
for (uint256 i = 0; i < tokens.length; i++) {
|
||||
deal(address(tokens[i]), fillerAddr, 100 ether);
|
||||
}
|
||||
|
||||
// Not role ADMIN
|
||||
vm.startPrank(BOB);
|
||||
vm.expectRevert();
|
||||
filler.withdraw(tokens, ADMIN);
|
||||
vm.stopPrank();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user