Skip to content

Commit c968561

Browse files
authored
add multicall adapter (#118)
* add multicall adapter * remove console log * address comments, fix some tests
1 parent 6ea5d64 commit c968561

File tree

7 files changed

+588
-3
lines changed

7 files changed

+588
-3
lines changed

contracts/test/MulticallAdapter.t.sol

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// SPDX-License-Identifier: Apache 2
2+
pragma solidity ^0.8.13;
3+
4+
import {Test} from "forge-std/Test.sol";
5+
import "openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Proxy.sol";
6+
7+
import "test/multicall-adapter/MulticallAdapter.sol";
8+
import "test/multicall-adapter/Structs.sol";
9+
import "./MyToken.sol";
10+
import "./helpers/MulticallAdapterHarness.sol";
11+
12+
contract MockTarget {
13+
function doNothing() public {}
14+
}
15+
16+
contract MulticallAdapterUnitTest is Test {
17+
MulticallAdapterHarness multicallAdapter;
18+
MockTarget mockTarget;
19+
MyToken sellToken1;
20+
MyToken sellToken2;
21+
22+
function setUp() public {
23+
multicallAdapter = new MulticallAdapterHarness();
24+
mockTarget = new MockTarget();
25+
sellToken1 = new MyToken("SellToken1", "ST1");
26+
sellToken2 = new MyToken("SellToken2", "ST2");
27+
}
28+
29+
function testTransferSellTokens(uint256 amount1, uint256 amount2) public {
30+
TokenAmount[] memory tokens = new TokenAmount[](2);
31+
tokens[0] = TokenAmount(address(sellToken1), amount1);
32+
tokens[1] = TokenAmount(address(sellToken2), amount2);
33+
address executor = makeAddr("executor");
34+
sellToken1.mint(executor, amount1);
35+
sellToken2.mint(executor, amount2);
36+
37+
vm.startPrank(executor);
38+
39+
sellToken1.approve(address(multicallAdapter), amount1);
40+
sellToken2.approve(address(multicallAdapter), amount2);
41+
multicallAdapter.exposed_transferSellTokens(tokens);
42+
43+
vm.stopPrank();
44+
45+
assertEq(sellToken1.balanceOf(address(multicallAdapter)), amount1);
46+
assertEq(sellToken2.balanceOf(address(multicallAdapter)), amount2);
47+
assertEq(sellToken1.balanceOf(executor), 0);
48+
assertEq(sellToken2.balanceOf(executor), 0);
49+
}
50+
51+
function testApproveTokensRevokeAllowances(
52+
uint256 amount1,
53+
uint256 amount2
54+
) public {
55+
TokenToSend[] memory tokensToSend = new TokenToSend[](2);
56+
tokensToSend[0] = TokenToSend({
57+
tokenAmount: TokenAmount(address(sellToken1), amount1),
58+
destination: makeAddr("target1")
59+
});
60+
tokensToSend[1] = TokenToSend({
61+
tokenAmount: TokenAmount(address(sellToken2), amount2),
62+
destination: makeAddr("target2")
63+
});
64+
65+
multicallAdapter.exposed_approveTokens(tokensToSend);
66+
67+
assertEq(
68+
sellToken1.allowance(
69+
address(multicallAdapter),
70+
makeAddr("target1")
71+
),
72+
amount1
73+
);
74+
assertEq(
75+
sellToken2.allowance(
76+
address(multicallAdapter),
77+
makeAddr("target2")
78+
),
79+
amount2
80+
);
81+
82+
multicallAdapter.exposed_revokeAllowances(tokensToSend);
83+
84+
assertEq(
85+
sellToken1.allowance(
86+
address(multicallAdapter),
87+
makeAddr("target1")
88+
),
89+
0
90+
);
91+
assertEq(
92+
sellToken2.allowance(
93+
address(multicallAdapter),
94+
makeAddr("target2")
95+
),
96+
0
97+
);
98+
}
99+
100+
function testCallTargetContract() public {
101+
bytes memory targetCalldata = abi.encodeWithSelector(
102+
MockTarget.doNothing.selector
103+
);
104+
uint256 targetCallValue = 0;
105+
address targetContract = address(mockTarget);
106+
uint256 targetCallIndex = 0;
107+
108+
vm.expectCall(targetContract, targetCallValue, targetCalldata);
109+
multicallAdapter.exposed_callTargetContract(
110+
targetContract,
111+
targetCalldata,
112+
targetCallValue,
113+
targetCallIndex
114+
);
115+
}
116+
117+
function testSweepTokensTokenAmount(
118+
uint256 amount1,
119+
uint256 amount2
120+
) public {
121+
TokenAmount[] memory tokens = new TokenAmount[](2);
122+
tokens[0] = TokenAmount(address(sellToken1), amount1);
123+
tokens[1] = TokenAmount(address(sellToken2), amount2);
124+
address executor = makeAddr("executor");
125+
sellToken1.mint(address(multicallAdapter), amount1);
126+
sellToken2.mint(address(multicallAdapter), amount2);
127+
128+
vm.prank(executor);
129+
multicallAdapter.exposed_sweepTokensTokenAmount(tokens);
130+
131+
assertEq(sellToken1.balanceOf(address(multicallAdapter)), 0);
132+
assertEq(sellToken2.balanceOf(address(multicallAdapter)), 0);
133+
assertEq(sellToken1.balanceOf(executor), amount1);
134+
assertEq(sellToken2.balanceOf(executor), amount2);
135+
}
136+
137+
function testSweepTokensTokenToSend(
138+
uint256 amount1,
139+
uint256 amount2
140+
) public {
141+
TokenToSend[] memory tokensToSend = new TokenToSend[](2);
142+
tokensToSend[0] = TokenToSend({
143+
tokenAmount: TokenAmount(address(sellToken1), amount1),
144+
destination: makeAddr("target1")
145+
});
146+
tokensToSend[1] = TokenToSend({
147+
tokenAmount: TokenAmount(address(sellToken2), amount2),
148+
destination: makeAddr("target2")
149+
});
150+
address executor = makeAddr("executor");
151+
sellToken1.mint(address(multicallAdapter), amount1);
152+
sellToken2.mint(address(multicallAdapter), amount2);
153+
154+
vm.prank(executor);
155+
multicallAdapter.exposed_sweepTokensTokenToSend(tokensToSend);
156+
157+
assertEq(sellToken1.balanceOf(address(multicallAdapter)), 0);
158+
assertEq(sellToken2.balanceOf(address(multicallAdapter)), 0);
159+
assertEq(sellToken1.balanceOf(executor), amount1);
160+
assertEq(sellToken2.balanceOf(executor), amount2);
161+
}
162+
}

0 commit comments

Comments
 (0)