Skip to content

Commit

Permalink
add test functions for the conditional swap
Browse files Browse the repository at this point in the history
  • Loading branch information
alex0207s committed Feb 27, 2024
1 parent 374475d commit a647fbb
Show file tree
Hide file tree
Showing 2 changed files with 236 additions and 0 deletions.
168 changes: 168 additions & 0 deletions test/forkMainnet/ConditionalSwap/Fill.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import { IConditionalSwap } from "contracts/interfaces/IConditionalSwap.sol";
import { ConditionalOrderSwapTest } from "test/forkMainnet/ConditionalSwap/Setup.t.sol";
import { BalanceSnapshot, Snapshot } from "test/utils/BalanceSnapshot.sol";

contract ConFillTest is ConditionalOrderSwapTest {
using BalanceSnapshot for Snapshot;

function setUp() public override {
super.setUp();
}

function testBestBuyOrder() external {
Snapshot memory takerTakerToken = BalanceSnapshot.take({ owner: taker, token: defaultOrder.takerToken });
Snapshot memory takerMakerToken = BalanceSnapshot.take({ owner: taker, token: defaultOrder.makerToken });
Snapshot memory makerTakerToken = BalanceSnapshot.take({ owner: maker, token: defaultOrder.takerToken });
Snapshot memory makerMakerToken = BalanceSnapshot.take({ owner: maker, token: defaultOrder.makerToken });
Snapshot memory recTakerToken = BalanceSnapshot.take({ owner: recipient, token: defaultOrder.takerToken });
Snapshot memory recMakerToken = BalanceSnapshot.take({ owner: recipient, token: defaultOrder.makerToken });

// craft the `flagAndPeriod` of the defaultOrder for BestBuy case
uint256 flags = 1 << 253;
defaultOrder.flagsAndPeriod = flags;

defaultTakerSig = signConOrder(takerPrivateKey, defaultOrder, address(conditionalSwap));

vm.startPrank(maker);
conditionalSwap.fillConOrder(defaultOrder, defaultTakerSig, defaultOrder.takerTokenAmount, defaultOrder.makerTokenAmount, defaultSettlementData);
vm.stopPrank();

takerTakerToken.assertChange(-int256(defaultOrder.takerTokenAmount));
takerMakerToken.assertChange(int256(0));
makerTakerToken.assertChange(int256(defaultOrder.takerTokenAmount));
makerMakerToken.assertChange(-int256(defaultOrder.makerTokenAmount));
recTakerToken.assertChange(int256(0));
recMakerToken.assertChange(int256(defaultOrder.makerTokenAmount));
}

function testRepayment() external {
Snapshot memory takerTakerToken = BalanceSnapshot.take({ owner: taker, token: defaultOrder.takerToken });
Snapshot memory takerMakerToken = BalanceSnapshot.take({ owner: taker, token: defaultOrder.makerToken });
Snapshot memory makerTakerToken = BalanceSnapshot.take({ owner: maker, token: defaultOrder.takerToken });
Snapshot memory makerMakerToken = BalanceSnapshot.take({ owner: maker, token: defaultOrder.makerToken });
Snapshot memory recTakerToken = BalanceSnapshot.take({ owner: recipient, token: defaultOrder.takerToken });
Snapshot memory recMakerToken = BalanceSnapshot.take({ owner: recipient, token: defaultOrder.makerToken });

// craft the `flagAndPeriod` of the defaultOrder for BestBuy case
uint256 flags = 7 << 253;
uint256 period = 12 hours;
uint256 numberOfCycles = (defaultExpiry - block.timestamp) / period;
defaultOrder.flagsAndPeriod = flags | period;

defaultTakerSig = signConOrder(takerPrivateKey, defaultOrder, address(conditionalSwap));
vm.startPrank(maker);
for (uint256 i; i < numberOfCycles; ++i) {
conditionalSwap.fillConOrder(defaultOrder, defaultTakerSig, defaultOrder.takerTokenAmount, defaultOrder.makerTokenAmount, defaultSettlementData);
vm.warp(block.timestamp + period);
}
vm.stopPrank();

takerTakerToken.assertChange(-int256(defaultOrder.takerTokenAmount) * int256(numberOfCycles));
takerMakerToken.assertChange(int256(0));
makerTakerToken.assertChange(int256(defaultOrder.takerTokenAmount) * int256(numberOfCycles));
makerMakerToken.assertChange(-int256(defaultOrder.makerTokenAmount) * int256(numberOfCycles));
recTakerToken.assertChange(int256(0));
recMakerToken.assertChange(int256(defaultOrder.makerTokenAmount) * int256(numberOfCycles));
}

function testDCAOrder() public {
// craft the `flagAndPeriod` of the defaultOrder for BestBuy case
uint256 flags = 7 << 253;
uint256 period = 1 days;

defaultOrder.flagsAndPeriod = flags | period;
}

function testCannotFillExpiredOrder() public {
vm.warp(defaultOrder.expiry + 1);

vm.expectRevert(IConditionalSwap.ExpiredOrder.selector);
vm.startPrank(maker);
conditionalSwap.fillConOrder(defaultOrder, defaultTakerSig, defaultOrder.takerTokenAmount, defaultOrder.makerTokenAmount, defaultSettlementData);
vm.stopPrank();
}

function testCannotFillOrderByInvalidOderMaker() public {
address invalidOrderMaker = makeAddr("invalidOrderMaker");

vm.expectRevert(IConditionalSwap.NotOrderMaker.selector);
vm.startPrank(invalidOrderMaker);
conditionalSwap.fillConOrder(defaultOrder, defaultTakerSig, defaultOrder.takerTokenAmount, defaultOrder.makerTokenAmount, defaultSettlementData);
vm.stopPrank();
}

function testCannotFillOrderWithZeroTakerTokenAmount() public {
vm.expectRevert(IConditionalSwap.ZeroTokenAmount.selector);
vm.startPrank(maker);
conditionalSwap.fillConOrder(defaultOrder, defaultTakerSig, 0, defaultOrder.makerTokenAmount, defaultSettlementData);
vm.stopPrank();
}

function testCannotFillOrderWithInvalidTotalTakerTokenAmount() public {
// craft the `flagAndPeriod` of the defaultOrder for BestBuy case
uint256 flags = 1 << 253;
defaultOrder.flagsAndPeriod = flags;

defaultTakerSig = signConOrder(takerPrivateKey, defaultOrder, address(conditionalSwap));

vm.startPrank(maker);
// the first fill with full takerTokenAmount
conditionalSwap.fillConOrder(defaultOrder, defaultTakerSig, defaultOrder.takerTokenAmount, defaultOrder.makerTokenAmount, defaultSettlementData);

vm.expectRevert(IConditionalSwap.InvalidTakingAmount.selector);
// The second fill with 1 takerTokenAmount would exceed the total cap this time.
conditionalSwap.fillConOrder(defaultOrder, defaultTakerSig, 1, defaultOrder.makerTokenAmount, defaultSettlementData);
vm.stopPrank();
}

function testCannotFillOrderWithInvalidSingleTakerTokenAmount() public {
// craft the `flagAndPeriod` of the defaultOrder for BestBuy case
uint256 flags = 7 << 253;
uint256 period = 12 hours;
defaultOrder.flagsAndPeriod = flags | period;

defaultTakerSig = signConOrder(takerPrivateKey, defaultOrder, address(conditionalSwap));

vm.expectRevert(IConditionalSwap.InvalidTakingAmount.selector);
vm.startPrank(maker);
conditionalSwap.fillConOrder(defaultOrder, defaultTakerSig, defaultOrder.takerTokenAmount + 1, defaultOrder.makerTokenAmount, defaultSettlementData);
vm.stopPrank();
}

function testCannotFillOrderWithInvalidZeroRecipient() public {
defaultOrder.recipient = payable(address(0));

vm.expectRevert(IConditionalSwap.InvalidRecipient.selector);
vm.startPrank(maker);
conditionalSwap.fillConOrder(defaultOrder, defaultTakerSig, defaultOrder.takerTokenAmount, defaultOrder.makerTokenAmount, defaultSettlementData);
vm.stopPrank();
}

function testCannotFillOrderWithIncorrectSignature() public {
uint256 randomPrivateKey = 1234;
bytes memory randomEOASig = signConOrder(randomPrivateKey, defaultOrder, address(conditionalSwap));

vm.expectRevert(IConditionalSwap.InvalidSignature.selector);
vm.startPrank(maker);
conditionalSwap.fillConOrder(defaultOrder, randomEOASig, defaultOrder.takerTokenAmount, defaultOrder.makerTokenAmount, defaultSettlementData);
vm.stopPrank();
}

function testCannotFillOrderWithinSamePeriod() public {
// craft the `flagAndPeriod` of the defaultOrder for BestBuy case
uint256 flags = 7 << 253;
uint256 period = 12 hours;
defaultOrder.flagsAndPeriod = flags | period;

defaultTakerSig = signConOrder(takerPrivateKey, defaultOrder, address(conditionalSwap));
vm.startPrank(maker);
conditionalSwap.fillConOrder(defaultOrder, defaultTakerSig, defaultOrder.takerTokenAmount, defaultOrder.makerTokenAmount, defaultSettlementData);
vm.warp(block.timestamp + 1);
vm.expectRevert(IConditionalSwap.InsufficientTimePassed.selector);
conditionalSwap.fillConOrder(defaultOrder, defaultTakerSig, defaultOrder.takerTokenAmount, defaultOrder.makerTokenAmount, defaultSettlementData);
vm.stopPrank();
}
}
68 changes: 68 additions & 0 deletions test/forkMainnet/ConditionalSwap/Setup.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import { Test } from "forge-std/Test.sol";
import { IWETH } from "contracts/interfaces/IWETH.sol";
import { IConditionalSwap } from "contracts/interfaces/IConditionalSwap.sol";
import { ConditionalSwap } from "contracts/ConditionalSwap.sol";
import { AllowanceTarget } from "contracts/AllowanceTarget.sol";
import { ConOrder, getConOrderHash } from "contracts/libraries/ConditionalOrder.sol";
import { Tokens } from "test/utils/Tokens.sol";
import { BalanceUtil } from "test/utils/BalanceUtil.sol";
import { SigHelper } from "test/utils/SigHelper.sol";
import { computeContractAddress } from "test/utils/Addresses.sol";
import { Permit2Helper } from "test/utils/Permit2Helper.sol";

contract ConditionalOrderSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper {
// role
address public conditionalOrderOwner = makeAddr("conditionalOrderOwner");
address public allowanceTargetOwner = makeAddr("allowanceTargetOwner");
uint256 public takerPrivateKey = uint256(1);
uint256 public makerPrivateKey = uint256(2);
address public taker = vm.addr(takerPrivateKey);
address payable public maker = payable(vm.addr(makerPrivateKey));
address payable public recipient = payable(makeAddr("recipient"));

uint256 public defaultExpiry = block.timestamp + 1 days;
uint256 public defaultSalt = 1234;
bytes public defaultTakerPermit;
bytes public defaultTakerSig;
bytes public defaultSettlementData;

ConditionalSwap conditionalSwap;
AllowanceTarget allowanceTarget;
ConOrder defaultOrder;

function setUp() public virtual {
// deploy allowance target
address[] memory trusted = new address[](1);
// pre-compute ConditionalOrderSwap address since the whitelist of allowance target is immutable
// NOTE: this assumes LimitOrderSwap is deployed right next to Allowance Target
trusted[0] = computeContractAddress(address(this), uint8(vm.getNonce(address(this)) + 1));

allowanceTarget = new AllowanceTarget(allowanceTargetOwner, trusted);
conditionalSwap = new ConditionalSwap(conditionalOrderOwner, UNISWAP_PERMIT2_ADDRESS, address(allowanceTarget));

deal(maker, 100 ether);
deal(taker, 100 ether);
setTokenBalanceAndApprove(maker, address(conditionalSwap), tokens, 100000);
setTokenBalanceAndApprove(taker, address(conditionalSwap), tokens, 100000);

defaultTakerPermit = hex"01";
defaultSettlementData = hex"00";

defaultOrder = ConOrder({
taker: taker,
maker: maker,
recipient: recipient,
takerToken: USDT_ADDRESS,
takerTokenAmount: 10 * 1e6,
makerToken: DAI_ADDRESS,
makerTokenAmount: 10 ether,
takerTokenPermit: defaultTakerPermit,
flagsAndPeriod: 0,
expiry: defaultExpiry,
salt: defaultSalt
});
}
}

0 comments on commit a647fbb

Please sign in to comment.