From 11bcd6e4a86f3e6c5b2c8e8d1b7543f87fc995ce Mon Sep 17 00:00:00 2001 From: telome <> Date: Wed, 17 Jan 2024 16:53:38 +0000 Subject: [PATCH] Exit dai to flapper --- src/FlapperUniV2.sol | 14 ++++---------- src/FlapperUniV2SwapOnly.sol | 12 +++++------- src/Splitter.sol | 13 +++++-------- test/FlapperUniV2.t.sol | 2 +- test/FlapperUniV2SwapOnly.t.sol | 2 +- test/Splitter.t.sol | 16 +--------------- test/mocks/SplitterMock.sol | 30 ++++++++++++++++++++---------- 7 files changed, 37 insertions(+), 52 deletions(-) diff --git a/src/FlapperUniV2.sol b/src/FlapperUniV2.sol index 2eedd99..16b913f 100644 --- a/src/FlapperUniV2.sol +++ b/src/FlapperUniV2.sol @@ -149,8 +149,8 @@ contract FlapperUniV2 { // (2) (lot - sell) / bought = (reserveDai + sell) / (reserveGem - bought) // // The solution for the these equations for variables `sell` and `bought` is used below. - function _getDaiToSell(uint256 wlot, uint256 reserveDai) internal pure returns (uint256 sell) { - sell = (Babylonian.sqrt(reserveDai * (wlot * 3988000 + reserveDai * 3988009)) - reserveDai * 1997) / 1994; + function _getDaiToSell(uint256 lot, uint256 reserveDai) internal pure returns (uint256 sell) { + sell = (Babylonian.sqrt(reserveDai * (lot * 3988000 + reserveDai * 3988009)) - reserveDai * 1997) / 1994; } // Based on: https://github.com/Uniswap/v2-periphery/blob/0335e8f7e1bd1e8d8329fd300aea2ef2f36dd19f/contracts/libraries/UniswapV2Library.sol#L43 @@ -165,18 +165,12 @@ contract FlapperUniV2 { // Check Amounts (uint256 _reserveDai, uint256 _reserveGem) = _getReserves(); - uint256 _wlot = lot / RAY; - uint256 _sell = _getDaiToSell(_wlot, _reserveDai); + uint256 _sell = _getDaiToSell(lot, _reserveDai); uint256 _buy = _getAmountOut(_sell, _reserveDai, _reserveGem); require(_buy >= _sell * want / (uint256(pip.read()) * RAY / spotter.par()), "FlapperUniV2/insufficient-buy-amount"); // - // Get Dai - vat.move(msg.sender, address(this), _wlot * RAY); - daiJoin.exit(address(this), _wlot); - // - // Swap GemLike(dai).transfer(address(pair), _sell); (uint256 _amt0Out, uint256 _amt1Out) = daiFirst ? (uint256(0), _buy) : (_buy, uint256(0)); @@ -184,7 +178,7 @@ contract FlapperUniV2 { // // Deposit - GemLike(dai).transfer(address(pair), _wlot - _sell); + GemLike(dai).transfer(address(pair), lot - _sell); GemLike(gem).transfer(address(pair), _buy); uint256 _liquidity = pair.mint(receiver); // diff --git a/src/FlapperUniV2SwapOnly.sol b/src/FlapperUniV2SwapOnly.sol index f548274..1095cff 100644 --- a/src/FlapperUniV2SwapOnly.sol +++ b/src/FlapperUniV2SwapOnly.sol @@ -33,6 +33,7 @@ interface SpotterLike { interface GemLike { function decimals() external view returns (uint8); + function transfer(address, uint256) external; } interface PipLike { @@ -141,15 +142,12 @@ contract FlapperUniV2SwapOnly { // Check Amount to buy (uint256 _reserveDai, uint256 _reserveGem) = _getReserves(); - uint256 _wlot = lot / RAY; - - uint256 _buy = _getAmountOut(_wlot, _reserveDai, _reserveGem); - require(_buy >= _wlot * want / (uint256(pip.read()) * RAY / spotter.par()), "FlapperUniV2SwapOnly/insufficient-buy-amount"); + uint256 _buy = _getAmountOut(lot, _reserveDai, _reserveGem); + require(_buy >= lot * want / (uint256(pip.read()) * RAY / spotter.par()), "FlapperUniV2SwapOnly/insufficient-buy-amount"); // - // Get Dai and swap - vat.move(msg.sender, address(this), _wlot * RAY); - daiJoin.exit(address(pair), _wlot); + // Swap + GemLike(dai).transfer(address(pair), lot); (uint256 _amt0Out, uint256 _amt1Out) = daiFirst ? (uint256(0), _buy) : (_buy, uint256(0)); pair.swap(_amt0Out, _amt1Out, receiver, new bytes(0)); // diff --git a/src/Splitter.sol b/src/Splitter.sol index 82b677a..cd3f80f 100644 --- a/src/Splitter.sol +++ b/src/Splitter.sol @@ -74,8 +74,8 @@ contract Splitter { _; } - uint256 internal constant WAD = 10 ** 18; uint256 internal constant RAY = 10 ** 27; + uint256 internal constant RAD = 10 ** 45; function rely(address usr) external auth { wards[usr] = 1; emit Rely(usr); } function deny(address usr) external auth { wards[usr] = 0; emit Deny(usr); } @@ -88,11 +88,7 @@ contract Splitter { } function file(bytes32 what, address data) external auth { - if (what == "flapper") { - vat.nope(address(flapper)); - flapper = FlapLike(data); - vat.hope(data); - } + if (what == "flapper") flapper = FlapLike(data); else revert("Splitter/file-unrecognized-param"); emit File(what, data); } @@ -103,12 +99,13 @@ contract Splitter { vat.move(msg.sender, address(this), tot); - uint256 lot = tot * burn / WAD; + uint256 lot = tot * burn / RAD; if (lot > 0) { + DaiJoinLike(daiJoin).exit(address(flapper), lot); flapper.exec(lot); } - uint256 pay = (tot - lot) / RAY; + uint256 pay = (tot / RAY - lot); if (pay > 0) { DaiJoinLike(daiJoin).exit(address(farm), pay); farm.notifyRewardAmount(pay); diff --git a/test/FlapperUniV2.t.sol b/test/FlapperUniV2.t.sol index afe88de..8a771d1 100644 --- a/test/FlapperUniV2.t.sol +++ b/test/FlapperUniV2.t.sol @@ -129,7 +129,7 @@ contract FlapperUniV2Test is DssTest { end = EndLike(ChainlogLike(LOG).getAddress("MCD_END")); spotter = SpotterLike(ChainlogLike(LOG).getAddress("MCD_SPOT")); - splitter = new SplitterMock(address(vat)); + splitter = new SplitterMock(DAI_JOIN); vm.startPrank(PAUSE_PROXY); vow.file("hump", 50_000_000 * RAD); vow.file("bump", 5707 * RAD); diff --git a/test/FlapperUniV2SwapOnly.t.sol b/test/FlapperUniV2SwapOnly.t.sol index a304bfe..06a1229 100644 --- a/test/FlapperUniV2SwapOnly.t.sol +++ b/test/FlapperUniV2SwapOnly.t.sol @@ -127,7 +127,7 @@ contract FlapperUniV2SwapOnlyTest is DssTest { end = EndLike(ChainlogLike(LOG).getAddress("MCD_END")); spotter = SpotterLike(ChainlogLike(LOG).getAddress("MCD_SPOT")); - splitter = new SplitterMock(address(vat)); + splitter = new SplitterMock(DAI_JOIN); vm.startPrank(PAUSE_PROXY); vow.file("hump", 50_000_000 * RAD); vow.file("bump", 5707 * RAD); diff --git a/test/Splitter.t.sol b/test/Splitter.t.sol index 2e3c165..758789b 100644 --- a/test/Splitter.t.sol +++ b/test/Splitter.t.sol @@ -259,7 +259,7 @@ contract SplitterTest is DssTest { uint256 prevLastUpdateTime = farm.lastUpdateTime(); vm.expectEmit(false, false, false, true); - emit Kick(vow.bump(), vow.bump() * splitter.burn() / WAD, farmReward); + emit Kick(vow.bump(), vow.bump() * splitter.burn() / RAD, farmReward); vow.flap(); assertEq(vat.dai(address(vow)), initialVowVatDai - vow.bump()); @@ -319,20 +319,6 @@ contract SplitterTest is DssTest { checkFileAddress(address(splitter), "Splitter", ["flapper"]); } - function testVatCanAfterFile() public { - assertEq(vat.can(address(splitter), address(0xf1)), 0); - - vm.prank(PAUSE_PROXY); splitter.file("flapper", address(0xf1)); - - assertEq(vat.can(address(splitter), address(0xf1)), 1); - assertEq(vat.can(address(splitter), address(0xf2)), 0); - - vm.prank(PAUSE_PROXY); splitter.file("flapper", address(0xf2)); - - assertEq(vat.can(address(splitter), address(0xf1)), 0); - assertEq(vat.can(address(splitter), address(0xf2)), 1); - } - function testKick() public { doKick(); } diff --git a/test/mocks/SplitterMock.sol b/test/mocks/SplitterMock.sol index 2f8bc3d..02b1193 100644 --- a/test/mocks/SplitterMock.sol +++ b/test/mocks/SplitterMock.sol @@ -8,33 +8,43 @@ interface VatLike { function nope(address) external; } +interface DaiJoinLike { + function vat() external view returns (address); + function exit(address, uint256) external; +} + interface FlapLike { function exec(uint256) external; function cage() external; } contract SplitterMock { + FlapLike public flapper; + + VatLike public immutable vat; + DaiJoinLike public immutable daiJoin; + constructor( - address _vat + address _daiJoin ) { - vat = VatLike(_vat); + daiJoin = DaiJoinLike(_daiJoin); + vat = VatLike(daiJoin.vat()); + + vat.hope(_daiJoin); } - FlapLike public flapper; - VatLike public immutable vat; + uint256 internal constant RAY = 10 ** 27; function file(bytes32 what, address data) external { - if (what == "flapper") { - vat.nope(address(flapper)); - flapper = FlapLike(data); - vat.hope(data); - } + if (what == "flapper") flapper = FlapLike(data); else revert("SplitterMock/file-unrecognized-param"); } function kick(uint256 tot, uint256) external returns (uint256) { vat.move(msg.sender, address(this), tot); - flapper.exec(tot); + uint256 lot = tot / RAY; + DaiJoinLike(daiJoin).exit(address(flapper), lot); + flapper.exec(lot); return 0; }