Skip to content

Commit efc8caa

Browse files
chore: migrate E2E internalBalances test to Foundry (#216)
## Description Migrate the internalBalances e2e test to foundry. Depends on #215. ## Test Plan CI ## Related Issues Closes #137
1 parent 884319e commit efc8caa

File tree

2 files changed

+225
-213
lines changed

2 files changed

+225
-213
lines changed

test/e2e/InternalBalances.t.sol

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
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 {IERC20} from "src/contracts/interfaces/IERC20.sol";
7+
import {IVault} from "src/contracts/interfaces/IVault.sol";
8+
9+
import {GPv2Order, GPv2Signing, SettlementEncoder} from "../libraries/encoders/SettlementEncoder.sol";
10+
import {Registry, TokenRegistry} from "../libraries/encoders/TokenRegistry.sol";
11+
import {Helper, IERC20Mintable} from "./Helper.sol";
12+
13+
using SettlementEncoder for SettlementEncoder.State;
14+
using TokenRegistry for TokenRegistry.State;
15+
using TokenRegistry for Registry;
16+
17+
interface IBalancerVault is IVault {
18+
function setRelayerApproval(address, address, bool) external;
19+
function getInternalBalance(address user, IERC20[] memory tokens) external view returns (uint256[] memory);
20+
function hasApprovedRelayer(address, address) external view returns (bool);
21+
}
22+
23+
contract InternalBalancesTest is Helper(false) {
24+
IERC20Mintable token1;
25+
IERC20Mintable token2;
26+
27+
function setUp() public override {
28+
super.setUp();
29+
30+
token1 = deployMintableErc20("TK1", "TK1");
31+
token2 = deployMintableErc20("TK2", "TK2");
32+
33+
vm.startPrank(address(settlement));
34+
token1.approve(address(vault), type(uint256).max);
35+
token2.approve(address(vault), type(uint256).max);
36+
vm.stopPrank();
37+
}
38+
39+
function test_should_settle_orders_buying_and_selling_with_internal_balances() external {
40+
Vm.Wallet memory trader1 = vm.createWallet("trader1");
41+
Vm.Wallet memory trader2 = vm.createWallet("trader2");
42+
Vm.Wallet memory trader3 = vm.createWallet("trader3");
43+
Vm.Wallet memory trader4 = vm.createWallet("trader4");
44+
45+
// mint some tokens to trader1
46+
_mintTokens(token1, trader1.addr, 1.001 ether);
47+
48+
// approve tokens to the balancer vault and approve the settlement contract to
49+
// be able to spend the balancer internal/external balances
50+
vm.startPrank(trader1.addr);
51+
token1.approve(address(vault), type(uint256).max);
52+
IBalancerVault(address(vault)).setRelayerApproval(trader1.addr, vaultRelayer, true);
53+
vm.stopPrank();
54+
55+
// place order for selling 1 token1 for 500 token2
56+
encoder.signEncodeTrade(
57+
vm,
58+
trader1,
59+
GPv2Order.Data({
60+
sellToken: token1,
61+
buyToken: token2,
62+
receiver: trader1.addr,
63+
sellAmount: 1 ether,
64+
buyAmount: 500 ether,
65+
validTo: 0xffffffff,
66+
appData: bytes32(uint256(1)),
67+
feeAmount: 0.001 ether,
68+
kind: GPv2Order.KIND_SELL,
69+
partiallyFillable: false,
70+
sellTokenBalance: GPv2Order.BALANCE_EXTERNAL,
71+
buyTokenBalance: GPv2Order.BALANCE_ERC20
72+
}),
73+
domainSeparator,
74+
GPv2Signing.Scheme.Eip712,
75+
0
76+
);
77+
78+
// mint some tokens to trader2
79+
_mintTokens(token2, trader2.addr, 300.3 ether);
80+
81+
// approve tokens to the balancer vault and deposit some tokens to balancer internal
82+
// balance
83+
vm.startPrank(trader2.addr);
84+
token2.approve(address(vault), type(uint256).max);
85+
IVault.UserBalanceOp[] memory ops = new IVault.UserBalanceOp[](1);
86+
ops[0] = IVault.UserBalanceOp({
87+
kind: IVault.UserBalanceOpKind.DEPOSIT_INTERNAL,
88+
asset: token2,
89+
amount: 300.3 ether,
90+
sender: trader2.addr,
91+
recipient: payable(trader2.addr)
92+
});
93+
vault.manageUserBalance(ops);
94+
IBalancerVault(address(vault)).setRelayerApproval(trader2.addr, vaultRelayer, true);
95+
vm.stopPrank();
96+
97+
// place order for buying 0.5 token1 with max 300 token2
98+
encoder.signEncodeTrade(
99+
vm,
100+
trader2,
101+
GPv2Order.Data({
102+
sellToken: token2,
103+
buyToken: token1,
104+
receiver: trader2.addr,
105+
sellAmount: 300 ether,
106+
buyAmount: 0.5 ether,
107+
validTo: 0xffffffff,
108+
appData: bytes32(uint256(1)),
109+
feeAmount: 0.3 ether,
110+
kind: GPv2Order.KIND_BUY,
111+
partiallyFillable: false,
112+
sellTokenBalance: GPv2Order.BALANCE_INTERNAL,
113+
buyTokenBalance: GPv2Order.BALANCE_ERC20
114+
}),
115+
domainSeparator,
116+
GPv2Signing.Scheme.Eip712,
117+
0
118+
);
119+
120+
// mint some tokens to trader3
121+
_mintTokens(token1, trader3.addr, 2.002 ether);
122+
123+
// approve the tokens to cow vault relayer
124+
vm.prank(trader3.addr);
125+
token1.approve(vaultRelayer, type(uint256).max);
126+
127+
// place order for selling 2 token1 for min 1000 token2
128+
encoder.signEncodeTrade(
129+
vm,
130+
trader3,
131+
GPv2Order.Data({
132+
sellToken: token1,
133+
buyToken: token2,
134+
receiver: trader3.addr,
135+
sellAmount: 2 ether,
136+
buyAmount: 1000 ether,
137+
validTo: 0xffffffff,
138+
appData: bytes32(uint256(1)),
139+
feeAmount: 0.002 ether,
140+
kind: GPv2Order.KIND_SELL,
141+
partiallyFillable: false,
142+
sellTokenBalance: GPv2Order.BALANCE_ERC20,
143+
buyTokenBalance: GPv2Order.BALANCE_INTERNAL
144+
}),
145+
domainSeparator,
146+
GPv2Signing.Scheme.Eip712,
147+
0
148+
);
149+
150+
// mint some tokens to trader4
151+
_mintTokens(token2, trader4.addr, 1501.5 ether);
152+
153+
// approve tokens to the balancer vault and deposit some tokens to balancer internal
154+
// balance
155+
vm.startPrank(trader4.addr);
156+
token2.approve(address(vault), type(uint256).max);
157+
ops = new IVault.UserBalanceOp[](1);
158+
ops[0] = IVault.UserBalanceOp({
159+
kind: IVault.UserBalanceOpKind.DEPOSIT_INTERNAL,
160+
asset: token2,
161+
amount: 1501.5 ether,
162+
sender: trader4.addr,
163+
recipient: payable(trader4.addr)
164+
});
165+
IBalancerVault(address(vault)).manageUserBalance(ops);
166+
IBalancerVault(address(vault)).setRelayerApproval(trader4.addr, vaultRelayer, true);
167+
vm.stopPrank();
168+
169+
// place order to buy 2.5 token1 with max 1500 token2
170+
encoder.signEncodeTrade(
171+
vm,
172+
trader4,
173+
GPv2Order.Data({
174+
sellToken: token2,
175+
buyToken: token1,
176+
receiver: trader4.addr,
177+
sellAmount: 1500 ether,
178+
buyAmount: 2.5 ether,
179+
validTo: 0xffffffff,
180+
appData: bytes32(uint256(1)),
181+
feeAmount: 1.5 ether,
182+
kind: GPv2Order.KIND_BUY,
183+
partiallyFillable: false,
184+
sellTokenBalance: GPv2Order.BALANCE_INTERNAL,
185+
buyTokenBalance: GPv2Order.BALANCE_INTERNAL
186+
}),
187+
domainSeparator,
188+
GPv2Signing.Scheme.Eip712,
189+
0
190+
);
191+
192+
// set token prices
193+
IERC20[] memory tokens = new IERC20[](2);
194+
tokens[0] = token1;
195+
tokens[1] = token2;
196+
uint256[] memory prices = new uint256[](2);
197+
prices[0] = 550;
198+
prices[1] = 1;
199+
encoder.tokenRegistry.tokenRegistry().setPrices(tokens, prices);
200+
201+
// settle the orders
202+
SettlementEncoder.EncodedSettlement memory encodedSettlement = encoder.encode(settlement);
203+
vm.prank(solver);
204+
settle(encodedSettlement);
205+
206+
assertEq(token2.balanceOf(trader1.addr), 550 ether, "trader1 amountOut not as expected");
207+
assertEq(token1.balanceOf(trader2.addr), 0.5 ether, "trader2 amountOut not as expected");
208+
assertEq(_getInternalBalance(address(token2), trader3.addr), 1100 ether, "trader3 amountOut not as expected");
209+
assertEq(_getInternalBalance(address(token1), trader4.addr), 2.5 ether, "trader4 amountOut not as expected");
210+
211+
assertEq(token1.balanceOf(address(settlement)), 0.003 ether, "token1 settlement fee amount not as expected");
212+
assertEq(token2.balanceOf(address(settlement)), 1.8 ether, "token2 settlement fee amount not as expected");
213+
}
214+
215+
function _mintTokens(IERC20Mintable token, address to, uint256 amt) internal {
216+
token.mint(to, amt);
217+
}
218+
219+
function _getInternalBalance(address token, address who) internal view returns (uint256) {
220+
IERC20[] memory tokens = new IERC20[](1);
221+
tokens[0] = IERC20(token);
222+
uint256[] memory bals = IBalancerVault(address(vault)).getInternalBalance(who, tokens);
223+
return bals[0];
224+
}
225+
}

0 commit comments

Comments
 (0)