@@ -62,6 +62,10 @@ interface GemLike {
6262 function transfer (address , uint256 ) external ;
6363}
6464
65+ interface Univ2FactoryLike {
66+ function createPair (address , address ) external returns (address );
67+ }
68+
6569contract MockMedianizer {
6670 uint256 public price;
6771 mapping (address => uint256 ) public bud;
@@ -85,55 +89,62 @@ contract FlapperUniV2Test is DssTest {
8589
8690 SplitterMock public splitter;
8791 FlapperUniV2 public flapper;
88- FlapperUniV2 public linkFlapper ;
92+ FlapperUniV2 public imxFlapper ;
8993 MockMedianizer public medianizer;
90- MockMedianizer public linkMedianizer ;
94+ MockMedianizer public imxMedianizer ;
9195
92- address DAI_JOIN ;
96+ address USDS_JOIN ;
9397 address SPOT;
94- address DAI ;
95- address MKR ;
98+ address USDS ;
99+ address SKY ;
96100 address USDC;
97- address LINK;
98101 address PAUSE_PROXY;
99102 VatLike vat;
100103 VowLike vow;
104+ address UNIV2_USDS_IMX_PAIR;
101105
102106 address constant LOG = 0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F ;
103107
108+ address constant IMX = 0xF57e7e7C23978C3cAEC3C3548E3D615c346e79fF ; // Random token that orders after USDS
104109 address constant UNIV2_FACTORY = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f ;
105- address constant UNIV2_DAI_MKR_PAIR = 0x517F9dD285e75b599234F7221227339478d0FcC8 ;
106- address constant UNIV2_LINK_DAI_PAIR = 0x6D4fd456eDecA58Cf53A8b586cd50754547DBDB2 ;
110+ address constant UNIV2_SKY_USDS_PAIR = 0x2621CC0B3F3c079c1Db0E80794AA24976F0b9e3c ;
107111
108112 event Exec (uint256 lot , uint256 sell , uint256 buy , uint256 liquidity );
109113
110114 function setUp () public {
111115 vm.createSelectFork (vm.envString ("ETH_RPC_URL " ));
112116
113- DAI_JOIN = ChainlogLike (LOG).getAddress ("MCD_JOIN_DAI " );
117+ USDS_JOIN = ChainlogLike (LOG).getAddress ("USDS_JOIN " );
114118 SPOT = ChainlogLike (LOG).getAddress ("MCD_SPOT " );
115- DAI = ChainlogLike (LOG).getAddress ("MCD_DAI " );
116- MKR = ChainlogLike (LOG).getAddress ("MCD_GOV " );
119+ USDS = ChainlogLike (LOG).getAddress ("USDS " );
120+ SKY = ChainlogLike (LOG).getAddress ("SKY " );
117121 USDC = ChainlogLike (LOG).getAddress ("USDC " );
118- LINK = ChainlogLike (LOG).getAddress ("LINK " );
119122 PAUSE_PROXY = ChainlogLike (LOG).getAddress ("MCD_PAUSE_PROXY " );
120123 vat = VatLike (ChainlogLike (LOG).getAddress ("MCD_VAT " ));
121124 vow = VowLike (ChainlogLike (LOG).getAddress ("MCD_VOW " ));
125+
126+ UNIV2_USDS_IMX_PAIR = Univ2FactoryLike (UNIV2_FACTORY).createPair (USDS, IMX);
122127
123- splitter = new SplitterMock (DAI_JOIN );
128+ splitter = new SplitterMock (USDS_JOIN );
124129 vm.startPrank (PAUSE_PROXY);
125130 vow.file ("hump " , 50_000_000 * RAD);
126131 vow.file ("bump " , 5707 * RAD);
127132 vow.file ("flapper " , address (splitter));
128133 vm.stopPrank ();
129134
130- (flapper, medianizer) = setUpFlapper (MKR, UNIV2_DAI_MKR_PAIR, 727 * WAD, "MCD_FLAP " ) ;
131- assertEq (flapper.usdsFirst (), true );
135+ {
136+ deal (IMX, UNIV2_USDS_IMX_PAIR, 200_000_0000 * WAD, true );
137+ deal (USDS, UNIV2_USDS_IMX_PAIR, 10_000_0000 * WAD, true );
138+ PairLike (UNIV2_USDS_IMX_PAIR).sync ();
139+ }
140+
141+ (flapper, medianizer) = setUpFlapper (SKY, UNIV2_SKY_USDS_PAIR, 727 * WAD, "MCD_FLAP " ) ;
142+ assertEq (flapper.usdsFirst (), false );
132143
133- (linkFlapper, linkMedianizer ) = setUpFlapper (LINK, UNIV2_LINK_DAI_PAIR , 654 * WAD / 100 , bytes32 (0 ));
134- assertEq (linkFlapper .usdsFirst (), false );
144+ (imxFlapper, imxMedianizer ) = setUpFlapper (IMX, UNIV2_USDS_IMX_PAIR , 654 * WAD / 100 , bytes32 (0 ));
145+ assertEq (imxFlapper .usdsFirst (), true );
135146
136- changeFlapper (address (flapper)); // Use MKR flapper by default
147+ changeFlapper (address (flapper)); // Use SKY flapper by default
137148
138149 // Create additional surplus if needed
139150 uint256 bumps = 2 * vow.bump (); // two kicks
@@ -160,7 +171,7 @@ contract FlapperUniV2Test is DssTest {
160171 deployer: address (this ),
161172 owner: PAUSE_PROXY,
162173 spotter: SPOT,
163- usds: DAI ,
174+ usds: USDS ,
164175 gem: gem,
165176 pair: pair,
166177 receiver: PAUSE_PROXY,
@@ -173,7 +184,7 @@ contract FlapperUniV2Test is DssTest {
173184 want: WAD * 97 / 100 ,
174185 pip: address (_medianizer),
175186 pair: pair,
176- usds: DAI ,
187+ usds: USDS ,
177188 splitter: address (splitter),
178189 prevChainlogKey: prevChainlogKey,
179190 chainlogKey: "MCD_FLAP_LP "
@@ -190,18 +201,18 @@ contract FlapperUniV2Test is DssTest {
190201 }
191202
192203 // Add initial liquidity if needed
193- (uint256 reserveDai , ) = UniswapV2Library.getReserves (UNIV2_FACTORY, DAI , gem);
194- uint256 minimalDaiReserve = 280_000 * WAD;
195- if (reserveDai < minimalDaiReserve ) {
204+ (uint256 reserveUsds , ) = UniswapV2Library.getReserves (UNIV2_FACTORY, USDS , gem);
205+ uint256 minimalUsdsReserve = 280_000 * WAD;
206+ if (reserveUsds < minimalUsdsReserve ) {
196207 _medianizer.setPrice (price);
197208 changeUniV2Price (price, gem, pair);
198- (reserveDai , ) = UniswapV2Library.getReserves (UNIV2_FACTORY, DAI , gem);
199- if (reserveDai < minimalDaiReserve ) {
200- topUpLiquidity (minimalDaiReserve - reserveDai , gem, pair);
209+ (reserveUsds , ) = UniswapV2Library.getReserves (UNIV2_FACTORY, USDS , gem);
210+ if (reserveUsds < minimalUsdsReserve ) {
211+ topUpLiquidity (minimalUsdsReserve - reserveUsds , gem, pair);
201212 }
202213 } else {
203214 // If there is initial liquidity, then the oracle price should be set to the current price
204- _medianizer.setPrice (uniV2DaiForGem (WAD, gem));
215+ _medianizer.setPrice (uniV2UsdsForGem (WAD, gem));
205216 }
206217 }
207218
@@ -213,37 +224,37 @@ contract FlapperUniV2Test is DssTest {
213224 return amountIn * WAD / (uint256 (MockMedianizer (pip).read ()) * RAY / SpotterLike (SPOT).par ());
214225 }
215226
216- function uniV2GemForDai (uint256 amountIn , address gem ) internal view returns (uint256 amountOut ) {
217- (uint256 reserveDai , uint256 reserveGem ) = UniswapV2Library.getReserves (UNIV2_FACTORY, DAI , gem);
218- amountOut = UniswapV2Library.getAmountOut (amountIn, reserveDai , reserveGem);
227+ function uniV2GemForUsds (uint256 amountIn , address gem ) internal view returns (uint256 amountOut ) {
228+ (uint256 reserveUsds , uint256 reserveGem ) = UniswapV2Library.getReserves (UNIV2_FACTORY, USDS , gem);
229+ amountOut = UniswapV2Library.getAmountOut (amountIn, reserveUsds , reserveGem);
219230 }
220231
221- function uniV2DaiForGem (uint256 amountIn , address gem ) internal view returns (uint256 amountOut ) {
222- (uint256 reserveDai , uint256 reserveGem ) = UniswapV2Library.getReserves (UNIV2_FACTORY, DAI , gem);
223- return UniswapV2Library.getAmountOut (amountIn, reserveGem, reserveDai );
232+ function uniV2UsdsForGem (uint256 amountIn , address gem ) internal view returns (uint256 amountOut ) {
233+ (uint256 reserveUsds , uint256 reserveGem ) = UniswapV2Library.getReserves (UNIV2_FACTORY, USDS , gem);
234+ return UniswapV2Library.getAmountOut (amountIn, reserveGem, reserveUsds );
224235 }
225236
226- function changeUniV2Price (uint256 daiForGem , address gem , address pair ) internal {
227- (uint256 reserveDai , uint256 reserveGem ) = UniswapV2Library.getReserves (UNIV2_FACTORY, DAI , gem);
228- uint256 currentDaiForGem = reserveDai * WAD / reserveGem;
237+ function changeUniV2Price (uint256 usdsForGem , address gem , address pair ) internal {
238+ (uint256 reserveUsds , uint256 reserveGem ) = UniswapV2Library.getReserves (UNIV2_FACTORY, USDS , gem);
239+ uint256 currentUsdsForGem = reserveUsds * WAD / reserveGem;
229240
230- // neededReserveDai * WAD / neededReserveMkr = daiForGem ;
231- if (currentDaiForGem > daiForGem ) {
232- deal (gem, pair, reserveDai * WAD / daiForGem );
241+ // neededReserveUsds * WAD / neededReserveSky = usdsForGem ;
242+ if (currentUsdsForGem > usdsForGem ) {
243+ deal (gem, pair, reserveUsds * WAD / usdsForGem );
233244 } else {
234- deal (DAI , pair, reserveGem * daiForGem / WAD);
245+ deal (USDS , pair, reserveGem * usdsForGem / WAD);
235246 }
236247 PairLike (pair).sync ();
237248 }
238249
239- function topUpLiquidity (uint256 daiAmt , address gem , address pair ) internal {
240- (uint256 reserveDai , uint256 reserveGem ) = UniswapV2Library.getReserves (UNIV2_FACTORY, DAI , gem);
241- uint256 gemAmt = UniswapV2Library.quote (daiAmt, reserveDai , reserveGem);
250+ function topUpLiquidity (uint256 usdsAmt , address gem , address pair ) internal {
251+ (uint256 reserveUsds , uint256 reserveGem ) = UniswapV2Library.getReserves (UNIV2_FACTORY, USDS , gem);
252+ uint256 gemAmt = UniswapV2Library.quote (usdsAmt, reserveUsds , reserveGem);
242253
243- deal (DAI , address (this ), GemLike (DAI ).balanceOf (address (this )) + daiAmt );
254+ deal (USDS , address (this ), GemLike (USDS ).balanceOf (address (this )) + usdsAmt );
244255 deal (gem, address (this ), GemLike (gem).balanceOf (address (this )) + gemAmt);
245256
246- GemLike (DAI ).transfer (pair, daiAmt );
257+ GemLike (USDS ).transfer (pair, usdsAmt );
247258 GemLike (gem).transfer (pair, gemAmt);
248259 uint256 liquidity = PairLike (pair).mint (address (this ));
249260 assertGt (liquidity, 0 );
@@ -252,41 +263,41 @@ contract FlapperUniV2Test is DssTest {
252263
253264 function marginalWant (address gem , address pip ) internal view returns (uint256 ) {
254265 uint256 wbump = vow.bump () / RAY;
255- (uint256 reserveDai , ) = UniswapV2Library.getReserves (UNIV2_FACTORY, DAI , gem);
256- uint256 sell = (Babylonian.sqrt (reserveDai * (wbump * 3_988_000 + reserveDai * 3_988_009 )) - reserveDai * 1997 ) / 1994 ;
266+ (uint256 reserveUsds , ) = UniswapV2Library.getReserves (UNIV2_FACTORY, USDS , gem);
267+ uint256 sell = (Babylonian.sqrt (reserveUsds * (wbump * 3_988_000 + reserveUsds * 3_988_009 )) - reserveUsds * 1997 ) / 1994 ;
257268
258- uint256 actual = uniV2GemForDai (sell, gem);
269+ uint256 actual = uniV2GemForUsds (sell, gem);
259270 uint256 ref = refAmountOut (sell, pip);
260271 return actual * WAD / ref;
261272 }
262273
263274 function doExec (address _flapper , address gem , address pair ) internal {
264275 uint256 initialLp = GemLike (pair).balanceOf (address (PAUSE_PROXY));
265276 uint256 initialDaiVow = vat.dai (address (vow));
266- uint256 initialReserveDai = GemLike (DAI ).balanceOf (pair);
267- uint256 initialReserveMkr = GemLike (gem).balanceOf (pair);
277+ uint256 initialReserveUsds = GemLike (USDS ).balanceOf (pair);
278+ uint256 initialReserveSky = GemLike (gem).balanceOf (pair);
268279
269280 vm.expectEmit (false , false , false , false ); // only check event signature (topic 0)
270281 emit Exec (0 , 0 , 0 , 0 );
271282 vow.flap ();
272283
273284 assertGt (GemLike (pair).balanceOf (address (PAUSE_PROXY)), initialLp);
274- assertEq (GemLike (DAI ).balanceOf (pair), initialReserveDai + vow.bump () / RAY);
275- assertEq (GemLike (gem).balanceOf (pair), initialReserveMkr );
285+ assertEq (GemLike (USDS ).balanceOf (pair), initialReserveUsds + vow.bump () / RAY);
286+ assertEq (GemLike (gem).balanceOf (pair), initialReserveSky );
276287 assertEq (initialDaiVow - vat.dai (address (vow)), vow.bump ());
277- assertEq (GemLike (DAI ).balanceOf (address (_flapper)), 0 );
288+ assertEq (GemLike (USDS ).balanceOf (address (_flapper)), 0 );
278289 assertEq (GemLike (gem).balanceOf (address (_flapper)), 0 );
279290 }
280291
281292 function testDefaultValues () public {
282- FlapperUniV2 f = new FlapperUniV2 (DAI_JOIN , SPOT, MKR, UNIV2_DAI_MKR_PAIR , PAUSE_PROXY);
293+ FlapperUniV2 f = new FlapperUniV2 (USDS_JOIN , SPOT, SKY, UNIV2_SKY_USDS_PAIR , PAUSE_PROXY);
283294 assertEq (f.want (), WAD);
284295 assertEq (f.wards (address (this )), 1 );
285296 }
286297
287298 function testIllegalGemDecimals () public {
288299 vm.expectRevert ("FlapperUniV2/gem-decimals-not-18 " );
289- flapper = new FlapperUniV2 (DAI_JOIN , SPOT, USDC, UNIV2_DAI_MKR_PAIR , PAUSE_PROXY);
300+ flapper = new FlapperUniV2 (USDS_JOIN , SPOT, USDC, UNIV2_SKY_USDS_PAIR , PAUSE_PROXY);
290301 }
291302
292303 function testAuth () public {
@@ -310,89 +321,89 @@ contract FlapperUniV2Test is DssTest {
310321 }
311322
312323 function testExec () public {
313- doExec (address (flapper), MKR, UNIV2_DAI_MKR_PAIR );
324+ doExec (address (flapper), SKY, UNIV2_SKY_USDS_PAIR );
314325 }
315326
316- function testExecDaiSecond () public {
317- changeFlapper (address (linkFlapper ));
318- doExec (address (linkFlapper ), LINK, UNIV2_LINK_DAI_PAIR );
327+ function testExecUsdsFirst () public {
328+ changeFlapper (address (imxFlapper ));
329+ doExec (address (imxFlapper ), IMX, UNIV2_USDS_IMX_PAIR );
319330 }
320331
321332 function testExecWantAllows () public {
322- uint256 _marginalWant = marginalWant (MKR , address (medianizer));
333+ uint256 _marginalWant = marginalWant (SKY , address (medianizer));
323334 vm.prank (PAUSE_PROXY); flapper.file ("want " , _marginalWant * 99 / 100 );
324- doExec (address (flapper), MKR, UNIV2_DAI_MKR_PAIR );
335+ doExec (address (flapper), SKY, UNIV2_SKY_USDS_PAIR );
325336 }
326337
327338 function testExecWantBlocks () public {
328- uint256 _marginalWant = marginalWant (MKR , address (medianizer));
339+ uint256 _marginalWant = marginalWant (SKY , address (medianizer));
329340 vm.prank (PAUSE_PROXY); flapper.file ("want " , _marginalWant * 101 / 100 );
330341 vm.expectRevert ("FlapperUniV2/insufficient-buy-amount " );
331342 vow.flap ();
332343 }
333344
334- function testExecDaiSecondWantBlocks () public {
335- changeFlapper (address (linkFlapper ));
336- uint256 _marginalWant = marginalWant (LINK , address (linkMedianizer ));
337- vm.prank (PAUSE_PROXY); linkFlapper .file ("want " , _marginalWant * 101 / 100 );
345+ function testExecUsdsFirstWantBlocks () public {
346+ changeFlapper (address (imxFlapper ));
347+ uint256 _marginalWant = marginalWant (IMX , address (imxMedianizer ));
348+ vm.prank (PAUSE_PROXY); imxFlapper .file ("want " , _marginalWant * 101 / 100 );
338349 vm.expectRevert ("FlapperUniV2/insufficient-buy-amount " );
339350 vow.flap ();
340351 }
341352
342- function testExecDonationDai () public {
343- deal (DAI, UNIV2_DAI_MKR_PAIR , GemLike (DAI ).balanceOf (UNIV2_DAI_MKR_PAIR ) * 1005 / 1000 );
353+ function testExecDonationUsds () public {
354+ deal (USDS, UNIV2_SKY_USDS_PAIR , GemLike (USDS ).balanceOf (UNIV2_SKY_USDS_PAIR ) * 1005 / 1000 );
344355 // This will now sync the reserves before the swap
345- doExec (address (flapper), MKR, UNIV2_DAI_MKR_PAIR );
356+ doExec (address (flapper), SKY, UNIV2_SKY_USDS_PAIR );
346357 }
347358
348359 function testExecDonationGem () public {
349- deal (MKR, UNIV2_DAI_MKR_PAIR , GemLike (MKR ).balanceOf (UNIV2_DAI_MKR_PAIR ) * 1005 / 1000 );
360+ deal (SKY, UNIV2_SKY_USDS_PAIR , GemLike (SKY ).balanceOf (UNIV2_SKY_USDS_PAIR ) * 1005 / 1000 );
350361 // This will now sync the reserves before the swap
351- doExec (address (flapper), MKR, UNIV2_DAI_MKR_PAIR );
362+ doExec (address (flapper), SKY, UNIV2_SKY_USDS_PAIR );
352363 }
353364
354365 // A shortened version of the sell and deposit flapper that sells `lot`.
355366 // Based on: https://github.com/makerdao/dss-flappers/blob/da7b6b70e7cfe3631f8af695bbe0c79db90e2a20/src/FlapperUniV2.sol
356367 function sellLotAndDeposit (PairLike pair , address gem , bool usdsFirst , address receiver , uint256 lot ) internal {
357368 // Get Amounts
358- (uint256 _reserveDai , uint256 _reserveGem ) = UniswapV2Library.getReserves (UNIV2_FACTORY, DAI , gem);
369+ (uint256 _reserveUsds , uint256 _reserveGem ) = UniswapV2Library.getReserves (UNIV2_FACTORY, USDS , gem);
359370 uint256 _wlot = lot / RAY;
360- uint256 _total = _wlot * (997 * _wlot + 1997 * _reserveDai ) / (1000 * _reserveDai );
361- uint256 _buy = _wlot * 997 * _reserveGem / (_reserveDai * 1000 + _wlot * 997 );
371+ uint256 _total = _wlot * (997 * _wlot + 1997 * _reserveUsds ) / (1000 * _reserveUsds );
372+ uint256 _buy = _wlot * 997 * _reserveGem / (_reserveUsds * 1000 + _wlot * 997 );
362373
363374 // Swap
364- GemLike (DAI ).transfer (address (pair), _wlot);
375+ GemLike (USDS ).transfer (address (pair), _wlot);
365376 (uint256 _amt0Out , uint256 _amt1Out ) = usdsFirst ? (uint256 (0 ), _buy) : (_buy, uint256 (0 ));
366377 pair.swap (_amt0Out, _amt1Out, address (this ), new bytes (0 ));
367378
368379 // Deposit
369- GemLike (DAI ).transfer (address (pair), _total - _wlot);
380+ GemLike (USDS ).transfer (address (pair), _total - _wlot);
370381 GemLike (gem).transfer (address (pair), _buy);
371382 pair.mint (receiver);
372383 }
373384
374385 function testEquivalenceToSellLotAndDeposit () public {
375- deal (DAI , address (this ), vow.bump () * 3 ); // certainly enough for the sell and deposit
376- GemLike (DAI ).approve (UNIV2_DAI_MKR_PAIR , vow.bump () * 3 );
386+ deal (USDS , address (this ), vow.bump () * 3 ); // certainly enough for the sell and deposit
387+ GemLike (USDS ).approve (UNIV2_SKY_USDS_PAIR , vow.bump () * 3 );
377388
378- uint256 initialDai = GemLike (DAI ).balanceOf (address (this ));
379- uint256 initialLp = GemLike (UNIV2_DAI_MKR_PAIR ).balanceOf (PAUSE_PROXY);
389+ uint256 initialUsds = GemLike (USDS ).balanceOf (address (this ));
390+ uint256 initialLp = GemLike (UNIV2_SKY_USDS_PAIR ).balanceOf (PAUSE_PROXY);
380391
381392 uint256 initialState = vm.snapshot ();
382393
383394 // Old version
384- sellLotAndDeposit (PairLike (UNIV2_DAI_MKR_PAIR ), MKR, true , PAUSE_PROXY, vow.bump ());
385- uint256 totalDaiConsumed = initialDai - GemLike (DAI ).balanceOf (address (this ));
386- uint256 boughtLpOldVersion = GemLike (UNIV2_DAI_MKR_PAIR ).balanceOf (PAUSE_PROXY) - initialLp;
395+ sellLotAndDeposit (PairLike (UNIV2_SKY_USDS_PAIR ), SKY, false , PAUSE_PROXY, vow.bump ());
396+ uint256 totalUsdsConsumed = initialUsds - GemLike (USDS ).balanceOf (address (this ));
397+ uint256 boughtLpOldVersion = GemLike (UNIV2_SKY_USDS_PAIR ).balanceOf (PAUSE_PROXY) - initialLp;
387398
388399 vm.revertTo (initialState);
389400
390401 // New version
391- vm.prank (PAUSE_PROXY); vow.file ("bump " , totalDaiConsumed * RAY); // The current flapper gets the total vat.dai to consume.
392- doExec (address (flapper), MKR, UNIV2_DAI_MKR_PAIR );
393- uint256 boughtLpNewVersion = GemLike (UNIV2_DAI_MKR_PAIR ).balanceOf (PAUSE_PROXY) - initialLp;
402+ vm.prank (PAUSE_PROXY); vow.file ("bump " , totalUsdsConsumed * RAY); // The current flapper gets the total vat.Usds to consume.
403+ doExec (address (flapper), SKY, UNIV2_SKY_USDS_PAIR );
404+ uint256 boughtLpNewVersion = GemLike (UNIV2_SKY_USDS_PAIR ).balanceOf (PAUSE_PROXY) - initialLp;
394405
395406 // Compare results for both versions
396- assertEq (boughtLpNewVersion, boughtLpOldVersion);
407+ assertApproxEqAbs (boughtLpNewVersion, boughtLpOldVersion, 10 );
397408 }
398409}
0 commit comments