From 6d00cb314b1e314227dd48fb61f213875ee83313 Mon Sep 17 00:00:00 2001 From: Abigail Date: Thu, 17 Mar 2022 12:15:22 -0500 Subject: [PATCH 1/7] curve stuff --- contracts/interfaces/curve.sol | 8 + .../strategies/bases/strategy-crv-base.sol | 27 +++ .../strategies/curve/strategy-crv-aave.sol | 190 ++++++++++++++++++ 3 files changed, 225 insertions(+) create mode 100644 contracts/strategies/bases/strategy-crv-base.sol create mode 100644 contracts/strategies/curve/strategy-crv-aave.sol diff --git a/contracts/interfaces/curve.sol b/contracts/interfaces/curve.sol index 0d5e6283a..de40d48df 100644 --- a/contracts/interfaces/curve.sol +++ b/contracts/interfaces/curve.sol @@ -79,6 +79,14 @@ interface ICurveFi_4 { function balances(int128) external view returns (uint256); } +interface ICurveFi_5 { + function add_liquidity( + uint256[] calldata _amounts, + uint256 _min_mint_amount, + bool _use_underlying + ) external returns (uint256); +} + interface ICurveZap_4 { function add_liquidity( uint256[4] calldata uamounts, diff --git a/contracts/strategies/bases/strategy-crv-base.sol b/contracts/strategies/bases/strategy-crv-base.sol new file mode 100644 index 000000000..f44a7fdce --- /dev/null +++ b/contracts/strategies/bases/strategy-crv-base.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.6.7; + +import "../strategy-base.sol"; + +abstract contract StrategyCrvBase is StrategyBase { + constructor( + address _want, + address _governance, + address _strategist, + address _controller, + address _timelock + ) + public StrategyBase( + _want, + _governance, + _strategist, + _controller, + _timelock + ) + {} + + + + + +} \ No newline at end of file diff --git a/contracts/strategies/curve/strategy-crv-aave.sol b/contracts/strategies/curve/strategy-crv-aave.sol new file mode 100644 index 000000000..24f44dd28 --- /dev/null +++ b/contracts/strategies/curve/strategy-crv-aave.sol @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.6.7; + +import "../bases/strategy-crv-base.sol"; + +contract StrategyCrvAave is StrategyCrvBase { + // stablecoins + address public constant daie = 0xd586E7F844cEa2F87f50152665BCbc2C279D8d70; + address public constant usdce = 0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664; + address public constant usdte = 0xc7198437980c041c805A1EDcbA50c1Ce5db95118; + + address public constant avdaie = 0x47AFa96Cdc9fAb46904A55a6ad4bf6660B53c38a; + address public constant avusdc = 0x46A51127C3ce23fb7AB1DE06226147F446e4a857; + address public constant avusdt = 0x532E6537FEA298397212F09A61e03311686f548e; + + + uint256 public constant am3d_poolId = 4; + address public constant lp = 0xaD556e7dc377d9089C6564f9E8d275f5EE4da22d; + address public constant swapLoan = 0x6EfbC734D91b229BE29137cf9fE531C1D3bf4Da6; + + constructor( + address _governance, + address _strategist, + address _controller, + address _timelock + ) + public + StrategyCrvBase( + swapLoan, + avai, + mim, + usdcE, + am3d_poolId, + lp, + _governance, + _strategist, + _controller, + _timelock + + ){} + + function _takeFeeOrcaToSnob(uint256 _keep) internal { + address[] memory path = new address[](3); + path[0] = orca; + path[1] = wavax; + path[2] = snob; + IERC20(orca).safeApprove(pangolinRouter, 0); + IERC20(orca).safeApprove(pangolinRouter, _keep); + _swapPangolinWithPath(path, _keep); + uint256 _snob = IERC20(snob).balanceOf(address(this)); + uint256 _share = _snob.mul(revenueShare).div(revenueShareMax); + IERC20(snob).safeTransfer(feeDistributor, _share); + IERC20(snob).safeTransfer( + IController(controller).treasury(), + _snob.sub(_share) + ); + } + + + function _orcaToToken(address _to) internal { + + // if it's mim then orca to wavax using pangolin and then wavax to mim using joe. + // if it's not mim then use pangolin with the three routing path. + uint256 _wavax = IERC20(wavax).balanceOf(address(this)); + uint256 _orca = IERC20(orca).balanceOf(address(this)); + IERC20(orca).safeApprove(pangolinRouter, 0); + IERC20(orca).safeApprove(pangolinRouter, _orca); + + if (_to == mim) { + _swapPangolin(orca, wavax, _orca); + + uint256 _postwavax = IERC20(wavax).balanceOf(address(this)); + IERC20(wavax).safeApprove(joeRouter, 0); + IERC20(wavax).safeApprove(joeRouter, _postwavax.sub(_wavax)); + _swapTraderJoe(wavax, _to, _postwavax.sub(_wavax)); + }else { + address[] memory path = new address[](3); + path[0] = orca; + path[1] = wavax; + path[2] = _to; + + _swapPangolinWithPath(path, _orca); + } + } + + // **** State Mutations **** + + function harvest() public onlyBenevolent override { + + // stablecoin we want to convert to + (address to) = getMostPremium(); + + // Collects Axial tokens + IMasterChefAxialV2(masterChefAxialV3).deposit(poolId, 0); + uint256 _axial = IERC20(axial).balanceOf(address(this)); + if (_axial > 0) { + // x% is sent back to the rewards holder + // to be used to lock up in as veCRV in a future date + uint256 _keep = _axial.mul(keep).div(keepMax); + if (_keep > 0) { + _takeFeeAxialToSnob(_keep); + } + + _axial = IERC20(axial).balanceOf(address(this)); + + IERC20(axial).safeApprove(joeRouter, 0); + IERC20(axial).safeApprove(joeRouter, _axial); + _swapTraderJoe(axial, to, _axial); + } + + uint256 _orca = IERC20(orca).balanceOf(address(this)); + if (_orca > 0) { + // x% is sent back to the rewards holder + // to be used to lock up in as veCRV in a future date + uint256 _keep = _orca.mul(keep).div(keepMax); + if (_keep > 0) { + _takeFeeOrcaToSnob(_keep); + } + + _orcaToToken(to); + } + + // Take Avax Rewards + uint256 _avax = address(this).balance; //get balance of native Avax + if (_avax > 0) { //wrap avax into ERC20 + WAVAX(wavax).deposit{value: _avax}(); + } + + uint256 _wavax = IERC20(wavax).balanceOf(address(this)); + if (_wavax > 0) { + uint256 _keep = _wavax.mul(keep).div(keepMax); + if (_keep > 0){ + _takeFeeWavaxToSnob(_keep); + } + + _wavax = IERC20(wavax).balanceOf(address(this)); + + //convert Avax Rewards + IERC20(wavax).safeApprove(joeRouter, 0); + IERC20(wavax).safeApprove(joeRouter, _wavax); + _swapTraderJoe(wavax, to, _wavax); + } + + // Adds liquidity to axial's as4d or ac4d pool + uint256 _to = IERC20(to).balanceOf(address(this)); + + if (_to > 0) { + IERC20(to).safeApprove(flashLoan, 0); + IERC20(to).safeApprove(flashLoan, _to); + + uint256[] memory liquidity = new uint256[](3); + + liquidity[0] = IERC20(pair1).balanceOf(address(this)); + liquidity[1] = IERC20(pair2).balanceOf(address(this)); + liquidity[2] = IERC20(pair3).balanceOf(address(this)); + + ISwap(flashLoan).addLiquidity(liquidity, 0, now + 60); + } + + // Donates DUST + _wavax = IERC20(wavax).balanceOf(address(this)); + if (_wavax > 0){ + IERC20(wavax).transfer( + IController(controller).treasury(), + _wavax + ); + } + _axial = IERC20(axial).balanceOf(address(this)); + if (_axial > 0){ + IERC20(axial).safeTransfer( + IController(controller).treasury(), + _axial + ); + } + _orca = IERC20(orca).balanceOf(address(this)); + if (_orca > 0){ + IERC20(orca).safeTransfer( + IController(controller).treasury(), + _orca + ); + } + + // We want to get back sCRV + _distributePerformanceFeesAndDeposit(); + } + + function getName() external override pure returns (string memory) { + return "StrategyAxialAA3DLp"; + } +} \ No newline at end of file From efac344e5ae4942617485ef55d599c1e5d621802 Mon Sep 17 00:00:00 2001 From: Abigail Date: Fri, 18 Mar 2022 12:14:32 -0500 Subject: [PATCH 2/7] slot & premium --- .../snowglobes/curve/snowglobe-crv-aave.sol | 131 ++++++++++++++ .../strategies/bases/strategy-crv-base.sol | 66 +++++++- .../strategies/curve/strategy-crv-aave.sol | 160 +++++------------- test/LPStrats/curve.test.ts | 19 +++ 4 files changed, 256 insertions(+), 120 deletions(-) create mode 100644 contracts/snowglobes/curve/snowglobe-crv-aave.sol create mode 100644 test/LPStrats/curve.test.ts diff --git a/contracts/snowglobes/curve/snowglobe-crv-aave.sol b/contracts/snowglobes/curve/snowglobe-crv-aave.sol new file mode 100644 index 000000000..6181f5918 --- /dev/null +++ b/contracts/snowglobes/curve/snowglobe-crv-aave.sol @@ -0,0 +1,131 @@ +// https://github.com/iearn-finance/vaults/blob/master/contracts/vaults/yVault.sol + +pragma solidity ^0.6.7; + +import "../../interfaces/controller.sol"; + +import "../../lib/erc20.sol"; +import "../../lib/safe-math.sol"; + +contract SnowGlobeCrvAave is ERC20 { + using SafeERC20 for IERC20; + using Address for address; + using SafeMath for uint256; + + IERC20 public token; + + uint256 public min = 9500; + uint256 public constant max = 10000; + + address public governance; + address public timelock; + address public controller; + + constructor(address _token, address _governance, address _timelock, address _controller) + public + ERC20( + string(abi.encodePacked("freezing ", ERC20(_token).name())), + string(abi.encodePacked("s", ERC20(_token).symbol())) + ) + { + _setupDecimals(ERC20(_token).decimals()); + token = IERC20(_token); + governance = _governance; + timelock = _timelock; + controller = _controller; + } + + function balance() public view returns (uint256) { + return + token.balanceOf(address(this)).add( + IController(controller).balanceOf(address(token)) + ); + } + + function setMin(uint256 _min) external { + require(msg.sender == governance, "!governance"); + require(_min <= max, "numerator cannot be greater than denominator"); + min = _min; + } + + function setGovernance(address _governance) public { + require(msg.sender == governance, "!governance"); + governance = _governance; + } + + function setTimelock(address _timelock) public { + require(msg.sender == timelock, "!timelock"); + timelock = _timelock; + } + + function setController(address _controller) public { + require(msg.sender == timelock, "!timelock"); + controller = _controller; + } + + // Custom logic in here for how much the globes allows to be borrowed + // Sets minimum required on-hand to keep small withdrawals cheap + function available() public view returns (uint256) { + return token.balanceOf(address(this)).mul(min).div(max); + } + + function earn() public { + uint256 _bal = available(); + token.safeTransfer(controller, _bal); + IController(controller).earn(address(token), _bal); + } + + function depositAll() external { + deposit(token.balanceOf(msg.sender)); + } + + function deposit(uint256 _amount) public { + uint256 _pool = balance(); + uint256 _before = token.balanceOf(address(this)); + token.safeTransferFrom(msg.sender, address(this), _amount); + uint256 _after = token.balanceOf(address(this)); + _amount = _after.sub(_before); // Additional check for deflationary tokens + uint256 shares = 0; + if (totalSupply() == 0) { + shares = _amount; + } else { + shares = (_amount.mul(totalSupply())).div(_pool); + } + _mint(msg.sender, shares); + } + + function withdrawAll() external { + withdraw(balanceOf(msg.sender)); + } + + // Used to swap any borrowed reserve over the debt limit to liquidate to 'token' + function harvest(address reserve, uint256 amount) external { + require(msg.sender == controller, "!controller"); + require(reserve != address(token), "token"); + IERC20(reserve).safeTransfer(controller, amount); + } + + // No rebalance implementation for lower fees and faster swaps + function withdraw(uint256 _shares) public { + uint256 r = (balance().mul(_shares)).div(totalSupply()); + _burn(msg.sender, _shares); + + // Check balance + uint256 b = token.balanceOf(address(this)); + if (b < r) { + uint256 _withdraw = r.sub(b); + IController(controller).withdraw(address(token), _withdraw); + uint256 _after = token.balanceOf(address(this)); + uint256 _diff = _after.sub(b); + if (_diff < _withdraw) { + r = b.add(_diff); + } + } + + token.safeTransfer(msg.sender, r); + } + + function getRatio() public view returns (uint256) { + return balance().mul(1e18).div(totalSupply()); + } +} diff --git a/contracts/strategies/bases/strategy-crv-base.sol b/contracts/strategies/bases/strategy-crv-base.sol index f44a7fdce..4812a9b78 100644 --- a/contracts/strategies/bases/strategy-crv-base.sol +++ b/contracts/strategies/bases/strategy-crv-base.sol @@ -1,9 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.6.7; -import "../strategy-base.sol"; +import "../strategy-joe-base.sol"; +import "../../interfaces/curve.sol"; +import "../../interfaces/wavax.sol"; + +abstract contract StrategyCrvBase is StrategyJoeBase { + address public gauge = 0x5B5CFE992AdAC0C9D48E05854B2d91C73a003858; + address public constant crv = 0x47536F17F4fF30e64A96a7555826b8f9e66ec468; + + address public liquidity = 0x7f90122BF0700F9E7e1F688fe926940E8839F353; -abstract contract StrategyCrvBase is StrategyBase { constructor( address _want, address _governance, @@ -11,7 +18,7 @@ abstract contract StrategyCrvBase is StrategyBase { address _controller, address _timelock ) - public StrategyBase( + public StrategyJoeBase( _want, _governance, _strategist, @@ -19,6 +26,59 @@ abstract contract StrategyCrvBase is StrategyBase { _timelock ) {} + + // **** Getters **** + + function balanceOfPool() public override view returns (uint256) { + uint256 amount = ICurveGauge(gauge).balanceOf(address(this)); + return amount; + } + + function getHarvestable() external view returns (uint256, uint256) { + uint256 pendingCrv = ICurveGauge(gauge).claimable_reward(address(this), crv); + uint256 pendingWavax = ICurveGauge(gauge).claimable_reward(address(this), wavax); + return (pendingCrv, pendingWavax); + } + + + // **** State Mutation functions **** + + function deposit() public override { + uint256 _want = IERC20(want).balanceOf(address(this)); + if (_want > 0) { + IERC20(want).safeApprove(gauge, 0); + IERC20(want).safeApprove(gauge, _want); + ICurveGauge(gauge).deposit(_want); + } + } + + function _withdrawSome(uint256 _amount) + internal + override + returns (uint256) + { + ICurveGauge(gauge).withdraw(_amount, true); + //ICurveGauge(gauge).withdraw(_amount); + return _amount; + } + + + function _takeFeeCrvToSnob(uint256 _keep) internal { + address[] memory path = new address[](3); + path[0] = crv; + path[1] = wavax; + path[2] = snob; + IERC20(crv).safeApprove(joeRouter, 0); + IERC20(crv).safeApprove(joeRouter, _keep); + _swapTraderJoeWithPath(path, _keep); + uint256 _snob = IERC20(snob).balanceOf(address(this)); + uint256 _share = _snob.mul(revenueShare).div(revenueShareMax); + IERC20(snob).safeTransfer(feeDistributor, _share); + IERC20(snob).safeTransfer( + IController(controller).treasury(), + _snob.sub(_share) + ); + } diff --git a/contracts/strategies/curve/strategy-crv-aave.sol b/contracts/strategies/curve/strategy-crv-aave.sol index 24f44dd28..215b6db74 100644 --- a/contracts/strategies/curve/strategy-crv-aave.sol +++ b/contracts/strategies/curve/strategy-crv-aave.sol @@ -13,11 +13,8 @@ contract StrategyCrvAave is StrategyCrvBase { address public constant avusdc = 0x46A51127C3ce23fb7AB1DE06226147F446e4a857; address public constant avusdt = 0x532E6537FEA298397212F09A61e03311686f548e; + address public constant aDai_aUsdc_aUsdt_lp = 0x1337BedC9D22ecbe766dF105c9623922A27963EC; - uint256 public constant am3d_poolId = 4; - address public constant lp = 0xaD556e7dc377d9089C6564f9E8d275f5EE4da22d; - address public constant swapLoan = 0x6EfbC734D91b229BE29137cf9fE531C1D3bf4Da6; - constructor( address _governance, address _strategist, @@ -26,12 +23,7 @@ contract StrategyCrvAave is StrategyCrvBase { ) public StrategyCrvBase( - swapLoan, - avai, - mim, - usdcE, - am3d_poolId, - lp, + aDai_aUsdc_aUsdt_lp, _governance, _strategist, _controller, @@ -39,144 +31,78 @@ contract StrategyCrvAave is StrategyCrvBase { ){} - function _takeFeeOrcaToSnob(uint256 _keep) internal { - address[] memory path = new address[](3); - path[0] = orca; - path[1] = wavax; - path[2] = snob; - IERC20(orca).safeApprove(pangolinRouter, 0); - IERC20(orca).safeApprove(pangolinRouter, _keep); - _swapPangolinWithPath(path, _keep); - uint256 _snob = IERC20(snob).balanceOf(address(this)); - uint256 _share = _snob.mul(revenueShare).div(revenueShareMax); - IERC20(snob).safeTransfer(feeDistributor, _share); - IERC20(snob).safeTransfer( - IController(controller).treasury(), - _snob.sub(_share) - ); - } - - - function _orcaToToken(address _to) internal { - - // if it's mim then orca to wavax using pangolin and then wavax to mim using joe. - // if it's not mim then use pangolin with the three routing path. - uint256 _wavax = IERC20(wavax).balanceOf(address(this)); - uint256 _orca = IERC20(orca).balanceOf(address(this)); - IERC20(orca).safeApprove(pangolinRouter, 0); - IERC20(orca).safeApprove(pangolinRouter, _orca); - - if (_to == mim) { - _swapPangolin(orca, wavax, _orca); - - uint256 _postwavax = IERC20(wavax).balanceOf(address(this)); - IERC20(wavax).safeApprove(joeRouter, 0); - IERC20(wavax).safeApprove(joeRouter, _postwavax.sub(_wavax)); - _swapTraderJoe(wavax, _to, _postwavax.sub(_wavax)); - }else { - address[] memory path = new address[](3); - path[0] = orca; - path[1] = wavax; - path[2] = _to; - - _swapPangolinWithPath(path, _orca); - } - } - // **** State Mutations **** function harvest() public onlyBenevolent override { + // Collects reward tokens + ICurveGauge(gauge).claim_rewards(); - // stablecoin we want to convert to - (address to) = getMostPremium(); - - // Collects Axial tokens - IMasterChefAxialV2(masterChefAxialV3).deposit(poolId, 0); - uint256 _axial = IERC20(axial).balanceOf(address(this)); - if (_axial > 0) { - // x% is sent back to the rewards holder - // to be used to lock up in as veCRV in a future date - uint256 _keep = _axial.mul(keep).div(keepMax); - if (_keep > 0) { - _takeFeeAxialToSnob(_keep); - } - - _axial = IERC20(axial).balanceOf(address(this)); - - IERC20(axial).safeApprove(joeRouter, 0); - IERC20(axial).safeApprove(joeRouter, _axial); - _swapTraderJoe(axial, to, _axial); + // Take Avax Rewards + uint256 _avax = address(this).balance; // get balance of native AVAX + if (_avax > 0) { // wrap AVAX into ERC20 + WAVAX(wavax).deposit{value: _avax}(); } + + uint256 _crv = IERC20(crv).balanceOf(address(this)); //get balance of crv tokens + uint256 _wavax = IERC20(wavax).balanceOf(address(this)); //get balance of wavax tokens - uint256 _orca = IERC20(orca).balanceOf(address(this)); - if (_orca > 0) { - // x% is sent back to the rewards holder - // to be used to lock up in as veCRV in a future date - uint256 _keep = _orca.mul(keep).div(keepMax); + // In the case of CRV Rewards, swap for daiE, usdce and usdte + if (_crv > 0) { + uint256 _keep = _crv.mul(keep).div(keepMax); if (_keep > 0) { - _takeFeeOrcaToSnob(_keep); + _takeFeeCrvToSnob(_keep); } - - _orcaToToken(to); - } - // Take Avax Rewards - uint256 _avax = address(this).balance; //get balance of native Avax - if (_avax > 0) { //wrap avax into ERC20 - WAVAX(wavax).deposit{value: _avax}(); + _crv = IERC20(crv).balanceOf(address(this)); + + IERC20(crv).safeApprove(joeRouter, 0); + IERC20(crv).safeApprove(joeRouter, _crv); + _swapTraderJoe(crv, daie, _crv); } - uint256 _wavax = IERC20(wavax).balanceOf(address(this)); if (_wavax > 0) { uint256 _keep = _wavax.mul(keep).div(keepMax); - if (_keep > 0){ + if (_keep > 0) { _takeFeeWavaxToSnob(_keep); } - + _wavax = IERC20(wavax).balanceOf(address(this)); - //convert Avax Rewards - IERC20(wavax).safeApprove(joeRouter, 0); - IERC20(wavax).safeApprove(joeRouter, _wavax); - _swapTraderJoe(wavax, to, _wavax); - } + IERC20(crv).safeApprove(joeRouter, 0); + IERC20(crv).safeApprove(joeRouter, _wavax); + _swapTraderJoe(wavax, daie, _wavax); - // Adds liquidity to axial's as4d or ac4d pool - uint256 _to = IERC20(to).balanceOf(address(this)); - - if (_to > 0) { - IERC20(to).safeApprove(flashLoan, 0); - IERC20(to).safeApprove(flashLoan, _to); + } + + // Adds liquidity to curve's aave pool + uint256 _daie = IERC20(daie).balanceOf(address(this)); + if (_daie > 0) { + IERC20(daie).safeApprove(liquidity, 0); + IERC20(daie).safeApprove(liquidity, _daie); - uint256[] memory liquidity = new uint256[](3); + uint256[] memory amounts = new uint256[](3); - liquidity[0] = IERC20(pair1).balanceOf(address(this)); - liquidity[1] = IERC20(pair2).balanceOf(address(this)); - liquidity[2] = IERC20(pair3).balanceOf(address(this)); + amounts[0] = _daie; + amounts[1] = 0; + amounts[2] = 0; - ISwap(flashLoan).addLiquidity(liquidity, 0, now + 60); + ICurveFi_5(liquidity).add_liquidity(amounts, 0, true); } // Donates DUST _wavax = IERC20(wavax).balanceOf(address(this)); + _crv = IERC20(crv).balanceOf(address(this)); if (_wavax > 0){ IERC20(wavax).transfer( IController(controller).treasury(), _wavax ); } - _axial = IERC20(axial).balanceOf(address(this)); - if (_axial > 0){ - IERC20(axial).safeTransfer( - IController(controller).treasury(), - _axial - ); - } - _orca = IERC20(orca).balanceOf(address(this)); - if (_orca > 0){ - IERC20(orca).safeTransfer( + + if (_crv > 0){ + IERC20(crv).safeTransfer( IController(controller).treasury(), - _orca + _crv ); } @@ -185,6 +111,6 @@ contract StrategyCrvAave is StrategyCrvBase { } function getName() external override pure returns (string memory) { - return "StrategyAxialAA3DLp"; + return "StrategyCrvAave"; } } \ No newline at end of file diff --git a/test/LPStrats/curve.test.ts b/test/LPStrats/curve.test.ts new file mode 100644 index 000000000..7d8c424c4 --- /dev/null +++ b/test/LPStrats/curve.test.ts @@ -0,0 +1,19 @@ +import { doStrategyTest } from "./../strategy-test"; +import { TestableStrategy, LPTestDefault } from "./../strategy-test-case"; + + +const tests = [ + { + name: "CrvAave", + controller: "backup", + timelockIsStrategist: true, + slot: 101 + }, +]; + +describe("Curve Strategy test", function() { + for (const test of tests) { + let Test: TestableStrategy = { ...LPTestDefault, ...test }; + doStrategyTest(Test); + } +}); \ No newline at end of file From 98c3615c360de2eb1a5facda2d6773a429d00e10 Mon Sep 17 00:00:00 2001 From: Abigail Date: Mon, 28 Mar 2022 23:00:46 -0500 Subject: [PATCH 3/7] searching for slot --- contracts/interfaces/curve.sol | 3 + .../strategies/bases/strategy-crv-base.sol | 55 +++++++++++++++- .../strategies/curve/strategy-crv-aave.sol | 62 +++++++++---------- 3 files changed, 84 insertions(+), 36 deletions(-) diff --git a/contracts/interfaces/curve.sol b/contracts/interfaces/curve.sol index de40d48df..6945ca66b 100644 --- a/contracts/interfaces/curve.sol +++ b/contracts/interfaces/curve.sol @@ -31,6 +31,9 @@ interface ICurveFi_3 { function add_liquidity(uint256[3] calldata amounts, uint256 min_mint_amount) external; + function add_liquidity(uint256[3] calldata amounts, uint256 min_mint_amount, bool _use_underlying) + external returns (uint256); + function remove_liquidity_imbalance( uint256[3] calldata amounts, uint256 max_burn_amount diff --git a/contracts/strategies/bases/strategy-crv-base.sol b/contracts/strategies/bases/strategy-crv-base.sol index 4812a9b78..17d9a3718 100644 --- a/contracts/strategies/bases/strategy-crv-base.sol +++ b/contracts/strategies/bases/strategy-crv-base.sol @@ -9,9 +9,18 @@ abstract contract StrategyCrvBase is StrategyJoeBase { address public gauge = 0x5B5CFE992AdAC0C9D48E05854B2d91C73a003858; address public constant crv = 0x47536F17F4fF30e64A96a7555826b8f9e66ec468; - address public liquidity = 0x7f90122BF0700F9E7e1F688fe926940E8839F353; + address public liquidity; + + // Underlying tokens in the pool + address public token1; + address public token2; + address public token3; constructor( + address _token1, + address _token2, + address _token3, + address _liquidity, address _want, address _governance, address _strategist, @@ -25,7 +34,12 @@ abstract contract StrategyCrvBase is StrategyJoeBase { _controller, _timelock ) - {} + { + liquidity = _liquidity; + token1 = _token1; + token2 = _token2; + token3 = _token3; + } // **** Getters **** @@ -62,6 +76,43 @@ abstract contract StrategyCrvBase is StrategyJoeBase { return _amount; } + // **** This function checks the balances of the underlying tokens in **** // + // **** the pool and returns the one with the least liquidity present **** // + function getMostPremium() + public + view + returns (address, uint256) + { + uint256[] memory balances = new uint256[](3); + balances[0] = ICurveFi_3(liquidity).balances(0); + balances[1] = ICurveFi_3(liquidity).balances(1).mul(10**12); + balances[2] = ICurveFi_3(liquidity).balances(2).mul(10**12); + + if ( + balances[0] < balances[1] && + balances[0] < balances[2] + ) { + return (token1, 0); + } + + if ( + balances[1] < balances[0] && + balances[1] < balances[2] + ) { + return (token2, 1); + } + + if ( + balances[2] < balances[0] && + balances[2] < balances[1] + ) { + return (token3, 2); + } + + // If they're somehow equal, we just want a random token + return (token1, 0); + } + function _takeFeeCrvToSnob(uint256 _keep) internal { address[] memory path = new address[](3); diff --git a/contracts/strategies/curve/strategy-crv-aave.sol b/contracts/strategies/curve/strategy-crv-aave.sol index 215b6db74..4e606961a 100644 --- a/contracts/strategies/curve/strategy-crv-aave.sol +++ b/contracts/strategies/curve/strategy-crv-aave.sol @@ -5,16 +5,14 @@ import "../bases/strategy-crv-base.sol"; contract StrategyCrvAave is StrategyCrvBase { // stablecoins - address public constant daie = 0xd586E7F844cEa2F87f50152665BCbc2C279D8d70; - address public constant usdce = 0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664; - address public constant usdte = 0xc7198437980c041c805A1EDcbA50c1Ce5db95118; - address public constant avdaie = 0x47AFa96Cdc9fAb46904A55a6ad4bf6660B53c38a; address public constant avusdc = 0x46A51127C3ce23fb7AB1DE06226147F446e4a857; address public constant avusdt = 0x532E6537FEA298397212F09A61e03311686f548e; address public constant aDai_aUsdc_aUsdt_lp = 0x1337BedC9D22ecbe766dF105c9623922A27963EC; + address public curve = 0x7f90122BF0700F9E7e1F688fe926940E8839F353; + constructor( address _governance, address _strategist, @@ -23,6 +21,10 @@ contract StrategyCrvAave is StrategyCrvBase { ) public StrategyCrvBase( + avdaie, + avusdc, + avusdt, + curve, aDai_aUsdc_aUsdt_lp, _governance, _strategist, @@ -34,59 +36,51 @@ contract StrategyCrvAave is StrategyCrvBase { // **** State Mutations **** function harvest() public onlyBenevolent override { + // retrieve underlying token we want to add liquidity to + (address to, ) = getMostPremium(); + // Collects reward tokens - ICurveGauge(gauge).claim_rewards(); + ICurveGauge(gauge).claim_rewards(address(this)); // Take Avax Rewards - uint256 _avax = address(this).balance; // get balance of native AVAX - if (_avax > 0) { // wrap AVAX into ERC20 + uint256 _avax = address(this).balance; // get balance of native AVAX + if (_avax > 0) { // wrap AVAX into ERC20 WAVAX(wavax).deposit{value: _avax}(); } - - uint256 _crv = IERC20(crv).balanceOf(address(this)); //get balance of crv tokens - uint256 _wavax = IERC20(wavax).balanceOf(address(this)); //get balance of wavax tokens - // In the case of CRV Rewards, swap for daiE, usdce and usdte + // Swap rewards for underlying token from getMostPremium(); + uint256 _crv = IERC20(crv).balanceOf(address(this)); // get balance of crv tokens if (_crv > 0) { - uint256 _keep = _crv.mul(keep).div(keepMax); - if (_keep > 0) { - _takeFeeCrvToSnob(_keep); - } - - _crv = IERC20(crv).balanceOf(address(this)); - - IERC20(crv).safeApprove(joeRouter, 0); - IERC20(crv).safeApprove(joeRouter, _crv); - _swapTraderJoe(crv, daie, _crv); + _swapTraderJoe(crv, wavax, _crv); } + uint256 _wavax = IERC20(wavax).balanceOf(address(this)); // get balance of wavax tokens if (_wavax > 0) { uint256 _keep = _wavax.mul(keep).div(keepMax); if (_keep > 0) { _takeFeeWavaxToSnob(_keep); } - - _wavax = IERC20(wavax).balanceOf(address(this)); - IERC20(crv).safeApprove(joeRouter, 0); - IERC20(crv).safeApprove(joeRouter, _wavax); - _swapTraderJoe(wavax, daie, _wavax); + _wavax = IERC20(wavax).balanceOf(address(this)); + IERC20(wavax).safeApprove(joeRouter, 0); + IERC20(wavax).safeApprove(joeRouter, _wavax); + _swapTraderJoe(wavax, to, _wavax); } // Adds liquidity to curve's aave pool - uint256 _daie = IERC20(daie).balanceOf(address(this)); - if (_daie > 0) { - IERC20(daie).safeApprove(liquidity, 0); - IERC20(daie).safeApprove(liquidity, _daie); + uint256 _to = IERC20(to).balanceOf(address(this)); + if (_to > 0) { + IERC20(to).safeApprove(curve, 0); + IERC20(to).safeApprove(curve, _to); uint256[] memory amounts = new uint256[](3); - amounts[0] = _daie; - amounts[1] = 0; - amounts[2] = 0; + amounts[0] = IERC20(avdaie).balanceOf(address(this)); + amounts[1] = IERC20(avusdc).balanceOf(address(this)); + amounts[2] = IERC20(avusdt).balanceOf(address(this)); - ICurveFi_5(liquidity).add_liquidity(amounts, 0, true); + ICurveFi_5(curve).add_liquidity(amounts, 0, true); } // Donates DUST From b513c83936529ce3c96300793b3fec049b8384de Mon Sep 17 00:00:00 2001 From: Abigail Date: Mon, 28 Mar 2022 23:03:00 -0500 Subject: [PATCH 4/7] slot --- .../strategies/bases/strategy-crv-base.sol | 25 +------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/contracts/strategies/bases/strategy-crv-base.sol b/contracts/strategies/bases/strategy-crv-base.sol index 17d9a3718..605ef5f2c 100644 --- a/contracts/strategies/bases/strategy-crv-base.sol +++ b/contracts/strategies/bases/strategy-crv-base.sol @@ -72,7 +72,6 @@ abstract contract StrategyCrvBase is StrategyJoeBase { returns (uint256) { ICurveGauge(gauge).withdraw(_amount, true); - //ICurveGauge(gauge).withdraw(_amount); return _amount; } @@ -109,30 +108,8 @@ abstract contract StrategyCrvBase is StrategyJoeBase { return (token3, 2); } - // If they're somehow equal, we just want a random token + // If they're somehow equal, we just want any underlying token return (token1, 0); } - - function _takeFeeCrvToSnob(uint256 _keep) internal { - address[] memory path = new address[](3); - path[0] = crv; - path[1] = wavax; - path[2] = snob; - IERC20(crv).safeApprove(joeRouter, 0); - IERC20(crv).safeApprove(joeRouter, _keep); - _swapTraderJoeWithPath(path, _keep); - uint256 _snob = IERC20(snob).balanceOf(address(this)); - uint256 _share = _snob.mul(revenueShare).div(revenueShareMax); - IERC20(snob).safeTransfer(feeDistributor, _share); - IERC20(snob).safeTransfer( - IController(controller).treasury(), - _snob.sub(_share) - ); - } - - - - - } \ No newline at end of file From b9e853618a2b59d01d27a2c22ebe12e4543f51ea Mon Sep 17 00:00:00 2001 From: Abigail Date: Tue, 29 Mar 2022 14:43:45 -0500 Subject: [PATCH 5/7] av bridge required --- contracts/interfaces/curve.sol | 2 + .../strategies/curve/strategy-crv-aave.sol | 40 ++++++++++++++----- test/LPStrats/curve.test.ts | 2 +- test/strategy-test.ts | 2 +- test/utils/helpers.ts | 2 +- 5 files changed, 35 insertions(+), 13 deletions(-) diff --git a/contracts/interfaces/curve.sol b/contracts/interfaces/curve.sol index 6945ca66b..3250bdc86 100644 --- a/contracts/interfaces/curve.sol +++ b/contracts/interfaces/curve.sol @@ -162,6 +162,8 @@ interface ICurveGauge { function claimable_reward(address, address) external view returns (uint256); function integrate_fraction(address arg0) external view returns (uint256); + + function bridge(address _token) external returns (bool); } interface ICurveMintr { diff --git a/contracts/strategies/curve/strategy-crv-aave.sol b/contracts/strategies/curve/strategy-crv-aave.sol index 4e606961a..84447c707 100644 --- a/contracts/strategies/curve/strategy-crv-aave.sol +++ b/contracts/strategies/curve/strategy-crv-aave.sol @@ -3,13 +3,20 @@ pragma solidity ^0.6.7; import "../bases/strategy-crv-base.sol"; +import "hardhat/console.sol"; + contract StrategyCrvAave is StrategyCrvBase { // stablecoins + address public daie = 0xd586E7F844cEa2F87f50152665BCbc2C279D8d70; + address public usdce = 0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664; + address public usdte = 0xc7198437980c041c805A1EDcbA50c1Ce5db95118; + + // avstablecoins address public constant avdaie = 0x47AFa96Cdc9fAb46904A55a6ad4bf6660B53c38a; - address public constant avusdc = 0x46A51127C3ce23fb7AB1DE06226147F446e4a857; - address public constant avusdt = 0x532E6537FEA298397212F09A61e03311686f548e; + address public constant avusdce = 0x46A51127C3ce23fb7AB1DE06226147F446e4a857; + address public constant avusdte = 0x532E6537FEA298397212F09A61e03311686f548e; - address public constant aDai_aUsdc_aUsdt_lp = 0x1337BedC9D22ecbe766dF105c9623922A27963EC; + address public constant aDaie_aUsdce_aUsdte_lp = 0x1337BedC9D22ecbe766dF105c9623922A27963EC; address public curve = 0x7f90122BF0700F9E7e1F688fe926940E8839F353; @@ -21,11 +28,11 @@ contract StrategyCrvAave is StrategyCrvBase { ) public StrategyCrvBase( - avdaie, - avusdc, - avusdt, + daie, + usdce, + usdte, curve, - aDai_aUsdc_aUsdt_lp, + aDaie_aUsdce_aUsdte_lp, _governance, _strategist, _controller, @@ -39,6 +46,8 @@ contract StrategyCrvAave is StrategyCrvBase { // retrieve underlying token we want to add liquidity to (address to, ) = getMostPremium(); + console.log("The token we want premium for is", to); + // Collects reward tokens ICurveGauge(gauge).claim_rewards(address(this)); @@ -50,6 +59,7 @@ contract StrategyCrvAave is StrategyCrvBase { // Swap rewards for underlying token from getMostPremium(); uint256 _crv = IERC20(crv).balanceOf(address(this)); // get balance of crv tokens + console.log("The amount of crv tokens we have after harvesting is", _crv); if (_crv > 0) { _swapTraderJoe(crv, wavax, _crv); } @@ -65,7 +75,9 @@ contract StrategyCrvAave is StrategyCrvBase { IERC20(wavax).safeApprove(joeRouter, 0); IERC20(wavax).safeApprove(joeRouter, _wavax); + _swapTraderJoe(wavax, to, _wavax); + } // Adds liquidity to curve's aave pool @@ -74,11 +86,19 @@ contract StrategyCrvAave is StrategyCrvBase { IERC20(to).safeApprove(curve, 0); IERC20(to).safeApprove(curve, _to); + ICurveGauge(0x06534b0BF7Ff378F162d4F348390BDA53b15fA35).bridge(to); + + uint256 _avto = IERC20(avusdte).balanceOf(address(this)); + console.log("The value of the avusdte after bridging is", _avto); + uint256[] memory amounts = new uint256[](3); - amounts[0] = IERC20(avdaie).balanceOf(address(this)); - amounts[1] = IERC20(avusdc).balanceOf(address(this)); - amounts[2] = IERC20(avusdt).balanceOf(address(this)); + amounts[0] = IERC20(daie).balanceOf(address(this)); + amounts[1] = IERC20(usdce).balanceOf(address(this)); + amounts[2] = IERC20(usdte).balanceOf(address(this)); + console.log("the amount of liquidity being added for token 1 is ", amounts[0]); + console.log("the amount of liquidity being added for token 2 is ", amounts[1]); + console.log("the amount of liquidity being added for token 3 is ", amounts[2]); ICurveFi_5(curve).add_liquidity(amounts, 0, true); } diff --git a/test/LPStrats/curve.test.ts b/test/LPStrats/curve.test.ts index 7d8c424c4..d1036e48e 100644 --- a/test/LPStrats/curve.test.ts +++ b/test/LPStrats/curve.test.ts @@ -7,7 +7,7 @@ const tests = [ name: "CrvAave", controller: "backup", timelockIsStrategist: true, - slot: 101 + slot: 2 }, ]; diff --git a/test/strategy-test.ts b/test/strategy-test.ts index 91bbdd9a5..820bf07f1 100644 --- a/test/strategy-test.ts +++ b/test/strategy-test.ts @@ -206,7 +206,7 @@ export function doStrategyTest(test_case: TestableStrategy) { await globeDepositWithdraw(assetContract, SnowGlobe, walletSigner); }); - it("Harvests should make some money!", async function() { + it.only("Harvests should make some money!", async function() { await harvestsMakeMoney(Strategy, harvester); }); diff --git a/test/utils/helpers.ts b/test/utils/helpers.ts index e1a1de320..198f3ea93 100644 --- a/test/utils/helpers.ts +++ b/test/utils/helpers.ts @@ -55,7 +55,7 @@ export function toGwei(amount: BigNumber): string { }; export async function overwriteTokenAmount(assetAddr: string, walletAddr: string, amount: string, slot: number = 0) { - const index = ethers.utils.solidityKeccak256(["uint256", "uint256"], [walletAddr, slot]); + const index = ethers.utils.solidityKeccak256(["uint256", "uint256"], [slot, walletAddr]); const BN = ethers.BigNumber.from(amount)._hex.toString(); const number = ethers.utils.hexZeroPad(BN, 32); From c7d50a1af38f237c79d2c56ce086e45aafbff9e3 Mon Sep 17 00:00:00 2001 From: Abigail Date: Fri, 1 Apr 2022 11:35:22 -0500 Subject: [PATCH 6/7] add_liquidity error --- contracts/interfaces/curve.sol | 2 + .../strategies/bases/strategy-crv-base.sol | 8 ++- .../strategies/curve/strategy-crv-aave.sol | 69 ++++++++++++++----- test/strategy-test.ts | 2 +- 4 files changed, 60 insertions(+), 21 deletions(-) diff --git a/contracts/interfaces/curve.sol b/contracts/interfaces/curve.sol index 3250bdc86..f18c1d9f1 100644 --- a/contracts/interfaces/curve.sol +++ b/contracts/interfaces/curve.sol @@ -164,6 +164,8 @@ interface ICurveGauge { function integrate_fraction(address arg0) external view returns (uint256); function bridge(address _token) external returns (bool); + + function add_liquidity(uint256[] calldata _amounts, uint256 _min_mint_amount, bool _use_underlying) external returns (uint256); } interface ICurveMintr { diff --git a/contracts/strategies/bases/strategy-crv-base.sol b/contracts/strategies/bases/strategy-crv-base.sol index 605ef5f2c..e0c6cc754 100644 --- a/contracts/strategies/bases/strategy-crv-base.sol +++ b/contracts/strategies/bases/strategy-crv-base.sol @@ -4,11 +4,15 @@ pragma solidity ^0.6.7; import "../strategy-joe-base.sol"; import "../../interfaces/curve.sol"; import "../../interfaces/wavax.sol"; +import "../../interfaces/aave.sol"; abstract contract StrategyCrvBase is StrategyJoeBase { address public gauge = 0x5B5CFE992AdAC0C9D48E05854B2d91C73a003858; address public constant crv = 0x47536F17F4fF30e64A96a7555826b8f9e66ec468; + address public constant lendingPool = 0x4F01AeD16D97E3aB5ab2B501154DC9bb0F1A5A2C; + uint16 public constant REFERRAL_CODE = 0xaa; + address public liquidity; // Underlying tokens in the pool @@ -84,8 +88,8 @@ abstract contract StrategyCrvBase is StrategyJoeBase { { uint256[] memory balances = new uint256[](3); balances[0] = ICurveFi_3(liquidity).balances(0); - balances[1] = ICurveFi_3(liquidity).balances(1).mul(10**12); - balances[2] = ICurveFi_3(liquidity).balances(2).mul(10**12); + balances[1] = ICurveFi_3(liquidity).balances(1); + balances[2] = ICurveFi_3(liquidity).balances(2); if ( balances[0] < balances[1] && diff --git a/contracts/strategies/curve/strategy-crv-aave.sol b/contracts/strategies/curve/strategy-crv-aave.sol index 84447c707..ba7cd21d2 100644 --- a/contracts/strategies/curve/strategy-crv-aave.sol +++ b/contracts/strategies/curve/strategy-crv-aave.sol @@ -43,11 +43,9 @@ contract StrategyCrvAave is StrategyCrvBase { // **** State Mutations **** function harvest() public onlyBenevolent override { - // retrieve underlying token we want to add liquidity to + // retrieve underlying token we want to add liquidity with (address to, ) = getMostPremium(); - console.log("The token we want premium for is", to); - // Collects reward tokens ICurveGauge(gauge).claim_rewards(address(this)); @@ -59,7 +57,6 @@ contract StrategyCrvAave is StrategyCrvBase { // Swap rewards for underlying token from getMostPremium(); uint256 _crv = IERC20(crv).balanceOf(address(this)); // get balance of crv tokens - console.log("The amount of crv tokens we have after harvesting is", _crv); if (_crv > 0) { _swapTraderJoe(crv, wavax, _crv); } @@ -81,31 +78,46 @@ contract StrategyCrvAave is StrategyCrvBase { } // Adds liquidity to curve's aave pool - uint256 _to = IERC20(to).balanceOf(address(this)); + uint256 _to = IERC20(to).balanceOf(address(this)); // the balance of the token we want to add liquidity with if (_to > 0) { - IERC20(to).safeApprove(curve, 0); - IERC20(to).safeApprove(curve, _to); + IERC20(to).safeApprove(lendingPool, 0); + IERC20(to).safeApprove(lendingPool, _to); + + ILendingPool(lendingPool).deposit( + to, + _to, + address(this), + REFERRAL_CODE + ); - ICurveGauge(0x06534b0BF7Ff378F162d4F348390BDA53b15fA35).bridge(to); + uint256[] memory amounts = new uint256[](3); - uint256 _avto = IERC20(avusdte).balanceOf(address(this)); - console.log("The value of the avusdte after bridging is", _avto); + uint256 _avdaie = IERC20(avdaie).balanceOf(address(this)); + uint256 _avusdce = IERC20(avusdce).balanceOf(address(this)); + uint256 _avusdte = IERC20(avusdte).balanceOf(address(this)); - uint256[] memory amounts = new uint256[](3); + amounts[0] = _avdaie; + amounts[1] = _avusdce; + amounts[2] = _avusdte; + + IERC20(avdaie).safeApprove(curve, 0); + IERC20(avdaie).safeApprove(curve, _avdaie); - amounts[0] = IERC20(daie).balanceOf(address(this)); - amounts[1] = IERC20(usdce).balanceOf(address(this)); - amounts[2] = IERC20(usdte).balanceOf(address(this)); - console.log("the amount of liquidity being added for token 1 is ", amounts[0]); - console.log("the amount of liquidity being added for token 2 is ", amounts[1]); - console.log("the amount of liquidity being added for token 3 is ", amounts[2]); + IERC20(avusdce).safeApprove(curve, 0); + IERC20(avusdce).safeApprove(curve, _avusdce); - ICurveFi_5(curve).add_liquidity(amounts, 0, true); + IERC20(avusdte).safeApprove(curve, 0); + IERC20(avusdte).safeApprove(curve, _avusdte); + + ICurveGauge(curve).add_liquidity(amounts, 0, false); } // Donates DUST _wavax = IERC20(wavax).balanceOf(address(this)); _crv = IERC20(crv).balanceOf(address(this)); + uint256 _daie = IERC20(daie).balanceOf(address(this)); + uint256 _usdce = IERC20(usdce).balanceOf(address(this)); + uint256 _usdte = IERC20(usdte).balanceOf(address(this)); if (_wavax > 0){ IERC20(wavax).transfer( IController(controller).treasury(), @@ -120,6 +132,27 @@ contract StrategyCrvAave is StrategyCrvBase { ); } + if (_daie > 0){ + IERC20(daie).safeTransfer( + IController(controller).treasury(), + _daie + ); + } + + if (_usdce > 0){ + IERC20(usdce).safeTransfer( + IController(controller).treasury(), + _usdce + ); + } + + if (_usdte > 0){ + IERC20(usdte).safeTransfer( + IController(controller).treasury(), + _usdte + ); + } + // We want to get back sCRV _distributePerformanceFeesAndDeposit(); } diff --git a/test/strategy-test.ts b/test/strategy-test.ts index 820bf07f1..91bbdd9a5 100644 --- a/test/strategy-test.ts +++ b/test/strategy-test.ts @@ -206,7 +206,7 @@ export function doStrategyTest(test_case: TestableStrategy) { await globeDepositWithdraw(assetContract, SnowGlobe, walletSigner); }); - it.only("Harvests should make some money!", async function() { + it("Harvests should make some money!", async function() { await harvestsMakeMoney(Strategy, harvester); }); From 504536d5e3c44579a89420396af1b57fae40f590 Mon Sep 17 00:00:00 2001 From: Abigail Date: Mon, 4 Apr 2022 14:26:08 -0500 Subject: [PATCH 7/7] add_liquidity --- contracts/interfaces/curve.sol | 2 +- contracts/strategies/curve/strategy-crv-aave.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/interfaces/curve.sol b/contracts/interfaces/curve.sol index f18c1d9f1..3708b35e2 100644 --- a/contracts/interfaces/curve.sol +++ b/contracts/interfaces/curve.sol @@ -165,7 +165,7 @@ interface ICurveGauge { function bridge(address _token) external returns (bool); - function add_liquidity(uint256[] calldata _amounts, uint256 _min_mint_amount, bool _use_underlying) external returns (uint256); + function add_liquidity(uint256[] calldata _amounts, uint256 _min_mint_amount) external returns (uint256); } interface ICurveMintr { diff --git a/contracts/strategies/curve/strategy-crv-aave.sol b/contracts/strategies/curve/strategy-crv-aave.sol index ba7cd21d2..6f1b049a1 100644 --- a/contracts/strategies/curve/strategy-crv-aave.sol +++ b/contracts/strategies/curve/strategy-crv-aave.sol @@ -109,7 +109,7 @@ contract StrategyCrvAave is StrategyCrvBase { IERC20(avusdte).safeApprove(curve, 0); IERC20(avusdte).safeApprove(curve, _avusdte); - ICurveGauge(curve).add_liquidity(amounts, 0, false); + ICurveGauge(curve).add_liquidity(amounts, 0); } // Donates DUST