Skip to content

Commit 5ed7d06

Browse files
0xSachinKrichardliang
authored andcommitted
Add BalancerV1ExchangeAdapter tests (#72)
* Add balancerV1ExchangeAdapter tests * Refactor uniswapV2ExchangeAdapter and add getDataParam test * Re-add deleted functions in deployAdapter.ts
1 parent 2a7700e commit 5ed7d06

File tree

5 files changed

+347
-23
lines changed

5 files changed

+347
-23
lines changed

Diff for: contracts/protocol/integration/exchange/BalancerV1ExchangeAdapter.sol

+14-5
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ contract BalancerV1ExchangeAdapter {
3434

3535
/* ============ State Variables ============ */
3636

37-
// Address of Uniswap V2 Router02 contract
37+
// Address of Balancer V1 Proxy contract
3838
address public immutable balancerProxy;
3939
// Balancer proxy function string for swapping exact tokens for a minimum of receive tokens
4040
string internal constant EXACT_IN = "smartSwapExactIn(address,address,uint256,uint256,uint256)";
@@ -99,15 +99,15 @@ contract BalancerV1ExchangeAdapter {
9999
/**
100100
* Generate data parameter to be passed to `getTradeCallData`. Returns encoded bool to select trade function.
101101
*
102-
* @param _sellComponent Address of the token to be sold
103-
* @param _buyComponent Address of the token to be bought
102+
* @param _sourceToken Address of the source token to be sold
103+
* @param _destinationToken Address of the destination token to buy
104104
* @param _fixIn Boolean representing if input tokens amount is fixed
105105
*
106106
* @return bytes Data parameter to be passed to `getTradeCallData`
107107
*/
108-
function generateDataParam(address _sellComponent, address _buyComponent, bool _fixIn)
108+
function generateDataParam(address _sourceToken, address _destinationToken, bool _fixIn)
109109
external
110-
view
110+
pure
111111
returns (bytes memory)
112112
{
113113
return abi.encode(_fixIn);
@@ -121,4 +121,13 @@ contract BalancerV1ExchangeAdapter {
121121
function getSpender() external view returns (address) {
122122
return balancerProxy;
123123
}
124+
125+
/**
126+
* Helper that returns the encoded data of boolean indicating the Balancer function to use
127+
*
128+
* @return bytes Encoded data used for trading on Balancer
129+
*/
130+
function getBalancerExchangeData(bool _shouldSwapFixedInputAmount) external pure returns (bytes memory) {
131+
return abi.encode(_shouldSwapFixedInputAmount);
132+
}
124133
}

Diff for: contracts/protocol/integration/exchange/UniswapV2ExchangeAdapterV2.sol

+7-7
Original file line numberDiff line numberDiff line change
@@ -104,20 +104,20 @@ contract UniswapV2ExchangeAdapterV2 {
104104
/**
105105
* Generate data parameter to be passed to `getTradeCallData`. Returns encoded trade paths and bool to select trade function.
106106
*
107-
* @param _sellComponent Address of the token to be sold
108-
* @param _buyComponent Address of the token to be bought
107+
* @param _sourceToken Address of the source token to be sold
108+
* @param _destinationToken Address of the destination token to buy
109109
* @param _fixIn Boolean representing if input tokens amount is fixed
110110
*
111111
* @return bytes Data parameter to be passed to `getTradeCallData`
112112
*/
113-
function generateDataParam(address _sellComponent, address _buyComponent, bool _fixIn)
113+
function generateDataParam(address _sourceToken, address _destinationToken, bool _fixIn)
114114
external
115-
view
115+
pure
116116
returns (bytes memory)
117117
{
118118
address[] memory path = new address[](2);
119-
path[0] = _sellComponent;
120-
path[1] = _buyComponent;
119+
path[0] = _sourceToken;
120+
path[1] = _destinationToken;
121121
return abi.encode(path, _fixIn);
122122
}
123123

@@ -135,7 +135,7 @@ contract UniswapV2ExchangeAdapterV2 {
135135
*
136136
* @return bytes Encoded data used for trading on Uniswap
137137
*/
138-
function getUniswapExchangeData(address[] memory _path, bool _shouldSwapExactTokensForTokens) external view returns (bytes memory) {
138+
function getUniswapExchangeData(address[] memory _path, bool _shouldSwapExactTokensForTokens) external pure returns (bytes memory) {
139139
return abi.encode(_path, _shouldSwapExactTokensForTokens);
140140
}
141141
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
import "module-alias/register";
2+
3+
import { BigNumber } from "@ethersproject/bignumber";
4+
import { defaultAbiCoder } from "ethers/lib/utils";
5+
6+
import { Address, Bytes } from "@utils/types";
7+
import { Account } from "@utils/test/types";
8+
import {
9+
EMPTY_BYTES,
10+
THREE,
11+
ZERO,
12+
} from "@utils/constants";
13+
import { BalancerV1ExchangeAdapter } from "@utils/contracts";
14+
import DeployHelper from "@utils/deploys";
15+
import {
16+
ether,
17+
} from "@utils/index";
18+
import {
19+
addSnapshotBeforeRestoreAfterEach,
20+
getAccounts,
21+
getSystemFixture,
22+
getBalancerFixture,
23+
getWaffleExpect
24+
} from "@utils/test/index";
25+
26+
import { SystemFixture, BalancerFixture } from "@utils/fixtures";
27+
28+
const expect = getWaffleExpect();
29+
30+
describe("BalancerV1ExchangeAdapter", () => {
31+
let owner: Account;
32+
let mockSetToken: Account;
33+
let deployer: DeployHelper;
34+
let setup: SystemFixture;
35+
let balancerSetup: BalancerFixture;
36+
37+
let balancerV1ExchangeAdapter: BalancerV1ExchangeAdapter;
38+
39+
before(async () => {
40+
[
41+
owner,
42+
mockSetToken,
43+
] = await getAccounts();
44+
45+
deployer = new DeployHelper(owner.wallet);
46+
setup = getSystemFixture(owner.address);
47+
await setup.initialize();
48+
49+
balancerSetup = getBalancerFixture(owner.address);
50+
await balancerSetup.initialize(
51+
owner,
52+
setup.weth,
53+
setup.wbtc,
54+
setup.dai
55+
);
56+
57+
balancerV1ExchangeAdapter = await deployer.adapters.deployBalancerV1ExchangeAdapter(balancerSetup.exchange.address);
58+
});
59+
60+
addSnapshotBeforeRestoreAfterEach();
61+
62+
describe("constructor", async () => {
63+
let subjectBalancerProxyAddress: Address;
64+
65+
beforeEach(async () => {
66+
subjectBalancerProxyAddress = balancerSetup.exchange.address;
67+
});
68+
69+
async function subject(): Promise<any> {
70+
return await deployer.adapters.deployBalancerV1ExchangeAdapter(subjectBalancerProxyAddress);
71+
}
72+
73+
it("should have the correct proxy address", async () => {
74+
const deployedBalancerV1ExchangeAdapter = await subject();
75+
76+
const actualProxyAddress = await deployedBalancerV1ExchangeAdapter.balancerProxy();
77+
expect(actualProxyAddress).to.eq(subjectBalancerProxyAddress);
78+
});
79+
});
80+
81+
describe("getSpender", async () => {
82+
async function subject(): Promise<any> {
83+
return await balancerV1ExchangeAdapter.getSpender();
84+
}
85+
86+
it("should return the correct spender address", async () => {
87+
const spender = await subject();
88+
89+
expect(spender).to.eq(balancerSetup.exchange.address);
90+
});
91+
});
92+
93+
describe("getBalancerExchangeData", async () => {
94+
let subjectShouldSwapFixedInputAmount: boolean;
95+
96+
beforeEach(async () => {
97+
subjectShouldSwapFixedInputAmount = true;
98+
});
99+
100+
async function subject(): Promise<any> {
101+
return await balancerV1ExchangeAdapter.getBalancerExchangeData(subjectShouldSwapFixedInputAmount);
102+
}
103+
104+
it("should return the correct data", async () => {
105+
const balancerData = await subject();
106+
const expectedData = defaultAbiCoder.encode(
107+
["bool"],
108+
[subjectShouldSwapFixedInputAmount]
109+
);
110+
111+
expect(balancerData).to.eq(expectedData);
112+
});
113+
});
114+
115+
describe("generateDataParam", async () => {
116+
let sourceToken: Address;
117+
let destinationToken: Address;
118+
119+
let subjectSourceToken: Address;
120+
let subjectDestinationToken: Address;
121+
let subjectFixIn: boolean;
122+
123+
beforeEach(async () => {
124+
sourceToken = setup.wbtc.address;
125+
destinationToken = setup.dai.address;
126+
127+
subjectSourceToken = sourceToken;
128+
subjectDestinationToken = destinationToken;
129+
});
130+
131+
async function subject(): Promise<any> {
132+
return await balancerV1ExchangeAdapter.generateDataParam(
133+
subjectSourceToken,
134+
subjectDestinationToken,
135+
subjectFixIn
136+
);
137+
}
138+
139+
describe("when boolean fixed input amount is true", async () => {
140+
beforeEach(async () => {
141+
subjectFixIn = true;
142+
});
143+
144+
it("should return the correct trade calldata", async () => {
145+
const dataParam = await subject();
146+
147+
const expectedDataParam = defaultAbiCoder.encode(
148+
["bool"],
149+
[subjectFixIn]
150+
);
151+
expect(JSON.stringify(dataParam)).to.eq(JSON.stringify(expectedDataParam));
152+
});
153+
});
154+
155+
describe("when boolean fixed input amount is false", async () => {
156+
beforeEach(async () => {
157+
subjectFixIn = false;
158+
});
159+
160+
it("should return the correct trade calldata", async () => {
161+
const dataParam = await subject();
162+
163+
const expectedDataParam = defaultAbiCoder.encode(
164+
["bool"],
165+
[subjectFixIn]
166+
);
167+
expect(JSON.stringify(dataParam)).to.eq(JSON.stringify(expectedDataParam));
168+
});
169+
});
170+
});
171+
172+
describe("getTradeCalldata", async () => {
173+
let sourceToken: Address;
174+
let destinationToken: Address;
175+
let sourceQuantity: BigNumber;
176+
let destinationQuantity: BigNumber;
177+
178+
let subjectMockSetToken: Address;
179+
let subjectSourceToken: Address;
180+
let subjectDestinationToken: Address;
181+
let subjectSourceQuantity: BigNumber;
182+
let subjectMinDestinationQuantity: BigNumber;
183+
let subjectData: Bytes;
184+
185+
beforeEach(async () => {
186+
sourceToken = setup.wbtc.address; // WBTC Address
187+
sourceQuantity = BigNumber.from(100000000); // Trade 1 WBTC
188+
destinationToken = setup.dai.address; // DAI Address
189+
destinationQuantity = ether(30000); // Receive at least 30k DAI
190+
191+
subjectSourceToken = sourceToken;
192+
subjectDestinationToken = destinationToken;
193+
subjectMockSetToken = mockSetToken.address;
194+
subjectSourceQuantity = sourceQuantity;
195+
subjectMinDestinationQuantity = destinationQuantity;
196+
subjectData = EMPTY_BYTES;
197+
});
198+
199+
async function subject(): Promise<any> {
200+
return await balancerV1ExchangeAdapter.getTradeCalldata(
201+
subjectSourceToken,
202+
subjectDestinationToken,
203+
subjectMockSetToken,
204+
subjectSourceQuantity,
205+
subjectMinDestinationQuantity,
206+
subjectData,
207+
);
208+
}
209+
210+
describe("when boolean fixed input amount is true", async () => {
211+
beforeEach(async () => {
212+
const shouldSwapFixedInputAmount = true;
213+
subjectData = defaultAbiCoder.encode(["bool"], [shouldSwapFixedInputAmount]);
214+
});
215+
216+
it("should return the correct trade calldata", async () => {
217+
const calldata = await subject();
218+
219+
const expectedCallData = balancerSetup.exchange.interface.encodeFunctionData("smartSwapExactIn", [
220+
sourceToken,
221+
destinationToken,
222+
sourceQuantity,
223+
destinationQuantity,
224+
THREE,
225+
]);
226+
expect(JSON.stringify(calldata)).to.eq(JSON.stringify([balancerSetup.exchange.address, ZERO, expectedCallData]));
227+
});
228+
});
229+
230+
describe("when boolean fixed input amount is false", async () => {
231+
beforeEach(async () => {
232+
const shouldSwapFixedInputAmount = false;
233+
subjectData = defaultAbiCoder.encode(["bool"], [shouldSwapFixedInputAmount]);
234+
});
235+
236+
it("should return the correct trade calldata", async () => {
237+
const calldata = await subject();
238+
239+
const expectedCallData = balancerSetup.exchange.interface.encodeFunctionData("smartSwapExactOut", [
240+
sourceToken,
241+
destinationToken,
242+
destinationQuantity, // Source and destination quantity are flipped for smartSwapExactOut
243+
sourceQuantity,
244+
THREE,
245+
]);
246+
expect(JSON.stringify(calldata)).to.eq(JSON.stringify([balancerSetup.exchange.address, ZERO, expectedCallData]));
247+
});
248+
});
249+
});
250+
});

0 commit comments

Comments
 (0)