Skip to content

Commit 884319e

Browse files
chore: migrate E2E nonStandardErc20 tests to Foundry (#213)
## Description Migrate nonStandardErc20 e2e test to foundry. Depends on `FoundryTest.sol` introduced in #215 ## Test Plan CI ## Related Issues Closes #138
1 parent f176400 commit 884319e

File tree

3 files changed

+157
-163
lines changed

3 files changed

+157
-163
lines changed

test/e2e/NonStandardErc20.t.sol

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// SPDX-License-Identifier: LGPL-3.0-or-later
2+
pragma solidity ^0.8;
3+
4+
import {Vm} from "forge-std/Vm.sol";
5+
6+
import {Helper} from "./Helper.sol";
7+
import {IERC20} from "src/contracts/interfaces/IERC20.sol";
8+
9+
import {GPv2Order, GPv2Signing, SettlementEncoder} from "../libraries/encoders/SettlementEncoder.sol";
10+
import {Registry, TokenRegistry} from "../libraries/encoders/TokenRegistry.sol";
11+
12+
abstract contract NonStandardERC20 {
13+
mapping(address => uint256) public balanceOf;
14+
mapping(address => mapping(address => uint256)) public allowance;
15+
16+
function mint(address to, uint256 amount) external {
17+
balanceOf[to] += amount;
18+
}
19+
20+
function approve(address spender, uint256 amount) external {
21+
allowance[msg.sender][spender] = amount;
22+
}
23+
24+
function transfer_(address to, uint256 amount) internal {
25+
balanceOf[msg.sender] -= amount;
26+
balanceOf[to] += amount;
27+
}
28+
29+
function transferFrom_(address from, address to, uint256 amount) internal {
30+
allowance[from][msg.sender] -= amount;
31+
balanceOf[from] -= amount;
32+
balanceOf[to] += amount;
33+
}
34+
}
35+
36+
contract ERC20NoReturn is NonStandardERC20 {
37+
function transfer(address to, uint256 amount) external {
38+
transfer_(to, amount);
39+
}
40+
41+
function transferFrom(address from, address to, uint256 amount) external {
42+
transferFrom_(from, to, amount);
43+
}
44+
}
45+
46+
contract ERC20ReturningUint is NonStandardERC20 {
47+
// Largest 256-bit prime :)
48+
uint256 private constant OK = 115792089237316195423570985008687907853269984665640564039457584007913129639747;
49+
50+
function transfer(address to, uint256 amount) external returns (uint256) {
51+
transfer_(to, amount);
52+
return OK;
53+
}
54+
55+
function transferFrom(address from, address to, uint256 amount) external returns (uint256) {
56+
transferFrom_(from, to, amount);
57+
return OK;
58+
}
59+
}
60+
61+
using SettlementEncoder for SettlementEncoder.State;
62+
using TokenRegistry for TokenRegistry.State;
63+
using TokenRegistry for Registry;
64+
65+
contract NonStandardErc20Test is Helper(false) {
66+
ERC20NoReturn noReturnToken;
67+
ERC20ReturningUint uintReturningToken;
68+
69+
function setUp() public override {
70+
super.setUp();
71+
72+
noReturnToken = new ERC20NoReturn();
73+
uintReturningToken = new ERC20ReturningUint();
74+
}
75+
76+
function test_should_allow_trading_non_standard_erc20_tokens() external {
77+
uint256 amount = 1 ether;
78+
uint256 feeAmount = 0.01 ether;
79+
80+
Vm.Wallet memory trader1 = vm.createWallet("trader1");
81+
Vm.Wallet memory trader2 = vm.createWallet("trader2");
82+
83+
// mint some noReturnToken tokens to trader1
84+
noReturnToken.mint(trader1.addr, amount + feeAmount);
85+
vm.prank(trader1.addr);
86+
noReturnToken.approve(vaultRelayer, type(uint256).max);
87+
// place order to swap noReturnToken for uintReturningToken
88+
encoder.signEncodeTrade(
89+
vm,
90+
trader1,
91+
GPv2Order.Data({
92+
sellToken: IERC20(address(noReturnToken)),
93+
buyToken: IERC20(address(uintReturningToken)),
94+
receiver: trader1.addr,
95+
sellAmount: amount,
96+
buyAmount: amount,
97+
validTo: 0xffffffff,
98+
appData: bytes32(uint256(1)),
99+
feeAmount: feeAmount,
100+
kind: GPv2Order.KIND_SELL,
101+
partiallyFillable: false,
102+
sellTokenBalance: GPv2Order.BALANCE_ERC20,
103+
buyTokenBalance: GPv2Order.BALANCE_ERC20
104+
}),
105+
domainSeparator,
106+
GPv2Signing.Scheme.Eip712,
107+
0
108+
);
109+
110+
// mint some uintReturningToken tokens to trader2
111+
uintReturningToken.mint(trader2.addr, amount + feeAmount);
112+
vm.prank(trader2.addr);
113+
uintReturningToken.approve(vaultRelayer, type(uint256).max);
114+
// place order to swap uintReturningToken for noReturnToken
115+
encoder.signEncodeTrade(
116+
vm,
117+
trader2,
118+
GPv2Order.Data({
119+
sellToken: IERC20(address(uintReturningToken)),
120+
buyToken: IERC20(address(noReturnToken)),
121+
receiver: trader2.addr,
122+
sellAmount: amount,
123+
buyAmount: amount,
124+
validTo: 0xffffffff,
125+
appData: bytes32(uint256(2)),
126+
feeAmount: feeAmount,
127+
kind: GPv2Order.KIND_BUY,
128+
partiallyFillable: false,
129+
sellTokenBalance: GPv2Order.BALANCE_ERC20,
130+
buyTokenBalance: GPv2Order.BALANCE_ERC20
131+
}),
132+
domainSeparator,
133+
GPv2Signing.Scheme.Eip712,
134+
0
135+
);
136+
137+
// set token prices
138+
IERC20[] memory tokens = new IERC20[](2);
139+
tokens[0] = IERC20(address(noReturnToken));
140+
tokens[1] = IERC20(address(uintReturningToken));
141+
uint256[] memory prices = new uint256[](2);
142+
prices[0] = 1;
143+
prices[1] = 1;
144+
encoder.tokenRegistry.tokenRegistry().setPrices(tokens, prices);
145+
146+
// settle the orders
147+
SettlementEncoder.EncodedSettlement memory encodedSettlement = encoder.encode(settlement);
148+
vm.prank(solver);
149+
settle(encodedSettlement);
150+
151+
assertEq(noReturnToken.balanceOf(address(settlement)), feeAmount, "order1 fee not charged as expected");
152+
assertEq(noReturnToken.balanceOf(trader2.addr), amount, "order1 swap output not as expected");
153+
154+
assertEq(uintReturningToken.balanceOf(address(settlement)), feeAmount, "order2 fee not charged as expected");
155+
assertEq(uintReturningToken.balanceOf(trader1.addr), amount, "order2 swap output not as expected");
156+
}
157+
}

test/e2e/nonStandardErc20.test.ts

Lines changed: 0 additions & 107 deletions
This file was deleted.

test/src/NonStandardERC20.sol

Lines changed: 0 additions & 56 deletions
This file was deleted.

0 commit comments

Comments
 (0)