From 49696d09bdcee79ba822684a6360e2b08f08caa5 Mon Sep 17 00:00:00 2001 From: corollari Date: Sun, 28 Mar 2021 03:55:39 +0200 Subject: [PATCH 1/8] Add alcx strategy --- implementations/strategy/StrategyAlchemix.sol | 132 ++++++++++++++++++ interfaces/external/AlcxStakingPools.sol | 51 +++++++ interfaces/external/MetaCurvePools.sol | 7 + 3 files changed, 190 insertions(+) create mode 100644 implementations/strategy/StrategyAlchemix.sol create mode 100644 interfaces/external/AlcxStakingPools.sol create mode 100644 interfaces/external/MetaCurvePools.sol diff --git a/implementations/strategy/StrategyAlchemix.sol b/implementations/strategy/StrategyAlchemix.sol new file mode 100644 index 0000000..c176eca --- /dev/null +++ b/implementations/strategy/StrategyAlchemix.sol @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.6.2; + +import "@openzeppelin/contracts/math/Math.sol"; +import "@openzeppelin/contracts/math/SafeMath.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; + +import "./Strategy.sol"; +import "../../interfaces/external/WETH.sol"; +import "../../interfaces/external/AlcxStakingPools.sol"; +import "../../interfaces/external/MetaCurvePools.sol"; + +contract StrategyAave is Strategy { + using SafeERC20 for IERC20; + using Address for address; + using SafeMath for uint256; + + address constant public alcx = 0xdbdb4d16eda451d0503b854cf79d55697f90c8df; + address constant public sushiRouter = 0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F; + address constant public weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // used for alcx <> weth <> usdt route + StakingPools public alcxStakingPools = StakingPools(0xAB8e74017a8Cc7c15FFcCd726603790d26d7DeCa); + address constant public alcx3CrvCurvePool = 0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c; + MetaCurvePools public metaCurvePools = MetaCurvePools(0xA79828DF1850E8a3A3064576f380D90aECDD3359); + uint256 constant public alcxCrvPoolId = 4; + int128 constant public usdtIndexInCrvMetapool = 3; + + + constructor(address _want) public Strategy(_want) { + } + + function update(address _newStratrgy) public override { + require(msg.sender == governance, "!governance"); + withdraw(1e18); // withdraw 100% + uint256 _balance = IERC20(want).balanceOf(address(this)); + IERC20(want).safeTransfer(_newStratrgy, _balance); + IVaultX(vaultX).setStrategy(_newStratrgy); + IVaultY(vaultY).setStrategy(_newStratrgy); + } + + function deposit(uint256 _ne18) public override { + require(msg.sender == strategist || msg.sender == governance, "!authorized"); + uint256 _amount = IERC20(want).balanceOf(address(this)).mul(_ne18).div(1e18); + IERC20(want).safeApprove(address(metaCurvePools), 0); + IERC20(want).safeApprove(address(metaCurvePools), _amount); + uint256[] memory amountsToAdd = new uint256[](4); + amountsToAdd[0] = 0; + amountsToAdd[1] = 0; + amountsToAdd[2] = 0; + amountsToAdd[2] = _amount; + metaCurvePools.add_liquidity(alcx3CrvCurvePool, amountsToAdd, uint256(0)); // Vulnerable to sandwich attacks but only strategist and governnace can call this so no flash loans attacks + it's stableswap + uint256 crvAmount = IERC20(alcx3CrvCurvePool).balanceOf(address(this)); + IERC20(alcx3CrvCurvePool).safeApprove(address(alcxStakingPools), 0); + IERC20(alcx3CrvCurvePool).safeApprove(address(alcxStakingPools), crvAmount); + alcxStakingPools.deposit(alcxCrvPoolId, crvAmount); + } + + function withdrawByAmount(uint256 _amount) internal { + alcxStakingPools.withdraw(alcxCrvPoolId, _amount); + IERC20(alcx3CrvCurvePool).safeApprove(address(metaCurvePools), 0); + IERC20(alcx3CrvCurvePool).safeApprove(address(metaCurvePools), _amount); + metaCurvePools.remove_liquidity_one_coin(address(alcx3CrvCurvePool), _amount, usdtIndexInCrvMetapool, 0); + } + + function harvest(uint minimumReceived) public { // Avoids sandwich attacks + require(msg.sender == strategist || msg.sender == governance, "!authorized"); + alcxStakingPools.claim(alcxCrvPoolId); + uint alcxBalance = IERC20(alcx).balanceOf(address(this)); + uint prevWantBalance = IERC20(want).balanceOf(address(this)); + if (alcxBalance > 0) { + IERC20(alcx).safeApprove(sushiRouter, 0); + IERC20(alcx).safeApprove(sushiRouter, alcxBalance); + + address[] memory path = new address[](3); + path[0] = alcx; + path[1] = weth; + path[2] = want; + + IUniV2(sushiRouter).swapExactTokensForTokens(alcxBalance, minimumReceived, path, address(this), now.add(1800)); + } + uint newWantBalance = IERC20(want).balanceOf(address(this)); + if (newWantBalance > prevWantBalance) { + deposit(newWantBalance.sub(prevWantBalance).mul(1e18).div(newWantBalance)); + } + } + + function withdraw(uint256 _ne18) public { + require(msg.sender == governance, "!governance"); + uint256 _amount = alcxStakingPools.getStakeTotalDeposited(address(this), alcxCrvPoolId).mul(_ne18).div(1e18); + if (_amount > 0) { + withdrawByAmount(_amount); + } + } + + function safeWithdraw(uint256 _amount) public { + require(msg.sender == governance, "!governance"); + withdrawByAmount(_amount); + } + + function withdraw(address _to, uint256 _amount) public override { + require(msg.sender == vaultX || msg.sender == vaultY, "!vault"); + + uint256 _balance = IERC20(want).balanceOf(address(this)); + + if (_balance < _amount) { + withdrawByAmount(_amount.sub(_balance)); + _amount = Math.min(IERC20(want).balanceOf(address(this)), _amount); + } + + if (msg.sender == vaultX) { + uint256 _fee = _amount.mul(feexe18).div(1e18); + IERC20(want).safeTransfer(governance, _fee); + IERC20(want).safeTransfer(_to, _amount.sub(_fee)); + } + else if (msg.sender == vaultY) { + uint256 _fee = _amount.mul(feeye18).div(1e18); + IERC20(want).safeTransfer(governance, _fee); + IERC20(want).safeTransfer(_to, _amount.sub(_fee)); + } + } + + function balanceOfY() public view override returns (uint256) { + uint stakedCrv = alcxStakingPools.getStakeTotalDeposited(address(this), alcxCrvPoolId); + uint balanceInCrv = metaCurvePools.calc_withdraw_one_coin(address(alcx3CrvCurvePool), stakedCrv, usdtIndexInCrvMetapool); + return IERC20(want).balanceOf(address(this)).add(balanceInCrv).sub(IERC20(vaultX).totalSupply()); + } + + // needs a payable function in order to receive ETH when redeem cETH. + receive() external payable {} +} + diff --git a/interfaces/external/AlcxStakingPools.sol b/interfaces/external/AlcxStakingPools.sol new file mode 100644 index 0000000..a7a209c --- /dev/null +++ b/interfaces/external/AlcxStakingPools.sol @@ -0,0 +1,51 @@ +pragma solidity ^0.6.2; + +interface StakingPools { + /// @dev Stakes tokens into a pool. + /// + /// @param _poolId the pool to deposit tokens into. + /// @param _depositAmount the amount of tokens to deposit. + function deposit(uint256 _poolId, uint256 _depositAmount) external; + + /// @dev Withdraws staked tokens from a pool. + /// + /// @param _poolId The pool to withdraw staked tokens from. + /// @param _withdrawAmount The number of tokens to withdraw. + function withdraw(uint256 _poolId, uint256 _withdrawAmount) external; + + /// @dev Claims all rewarded tokens from a pool. + /// + /// @param _poolId The pool to claim rewards from. + /// + /// @notice use this function to claim the tokens from a corresponding pool by ID. + function claim(uint256 _poolId) external; + + /// @dev Claims all rewards from a pool and then withdraws all staked tokens. + /// + /// @param _poolId the pool to exit from. + function exit(uint256 _poolId) external; + + /// @dev Gets the total amount of funds staked in a pool. + /// + /// @param _poolId the identifier of the pool. + /// + /// @return the total amount of staked or deposited tokens. + function getPoolTotalDeposited(uint256 _poolId) external view returns (uint256); + + + /// @dev Gets the number of tokens a user has staked into a pool. + /// + /// @param _account The account to query. + /// @param _poolId the identifier of the pool. + /// + /// @return the amount of deposited tokens. + function getStakeTotalDeposited(address _account, uint256 _poolId) external view returns (uint256); + + /// @dev Gets the number of unclaimed reward tokens a user can claim from a pool. + /// + /// @param _account The account to get the unclaimed balance of. + /// @param _poolId The pool to check for unclaimed rewards. + /// + /// @return the amount of unclaimed reward tokens a user has in a pool. + function getStakeTotalUnclaimed(address _account, uint256 _poolId) external view returns (uint256); +} \ No newline at end of file diff --git a/interfaces/external/MetaCurvePools.sol b/interfaces/external/MetaCurvePools.sol new file mode 100644 index 0000000..a8bb707 --- /dev/null +++ b/interfaces/external/MetaCurvePools.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.6.2; + +interface MetaCurvePools { + function add_liquidity(address _pool, uint256[4] calldata _deposit_amounts, uint256 _min_mint_amount) public; + function calc_withdraw_one_coin(address _pool, uint256 _token_amount, int128 i) external view returns (uint256); + function remove_liquidity_one_coin(address _pool, uint256 _token_amount, int128 i, uint256 min_amount) external; +} \ No newline at end of file From 24cf2f18c2f48dc41a42609f7759ba25f93dedce Mon Sep 17 00:00:00 2001 From: corollari Date: Sun, 28 Mar 2021 13:21:32 +0200 Subject: [PATCH 2/8] minor fixes --- implementations/strategy/StrategyAlchemix.sol | 24 ++++++++++--------- interfaces/external/MetaCurvePools.sol | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/implementations/strategy/StrategyAlchemix.sol b/implementations/strategy/StrategyAlchemix.sol index c176eca..4b7f38e 100644 --- a/implementations/strategy/StrategyAlchemix.sol +++ b/implementations/strategy/StrategyAlchemix.sol @@ -6,18 +6,20 @@ import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import "@openzeppelin/contracts/utils/Address.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; import "./Strategy.sol"; -import "../../interfaces/external/WETH.sol"; import "../../interfaces/external/AlcxStakingPools.sol"; import "../../interfaces/external/MetaCurvePools.sol"; +import "../../interfaces/external/Uniswap.sol"; -contract StrategyAave is Strategy { +// owner == harvester +contract StrategyAlchemix is Strategy, Ownable { using SafeERC20 for IERC20; using Address for address; using SafeMath for uint256; - address constant public alcx = 0xdbdb4d16eda451d0503b854cf79d55697f90c8df; + address constant public alcx = 0xdBdb4d16EdA451D0503b854CF79D55697F90c8DF; address constant public sushiRouter = 0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F; address constant public weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // used for alcx <> weth <> usdt route StakingPools public alcxStakingPools = StakingPools(0xAB8e74017a8Cc7c15FFcCd726603790d26d7DeCa); @@ -26,7 +28,6 @@ contract StrategyAave is Strategy { uint256 constant public alcxCrvPoolId = 4; int128 constant public usdtIndexInCrvMetapool = 3; - constructor(address _want) public Strategy(_want) { } @@ -40,15 +41,16 @@ contract StrategyAave is Strategy { } function deposit(uint256 _ne18) public override { - require(msg.sender == strategist || msg.sender == governance, "!authorized"); + require(msg.sender == owner() || msg.sender == governance, "!authorized"); uint256 _amount = IERC20(want).balanceOf(address(this)).mul(_ne18).div(1e18); IERC20(want).safeApprove(address(metaCurvePools), 0); IERC20(want).safeApprove(address(metaCurvePools), _amount); - uint256[] memory amountsToAdd = new uint256[](4); - amountsToAdd[0] = 0; - amountsToAdd[1] = 0; - amountsToAdd[2] = 0; - amountsToAdd[2] = _amount; + uint256[4] memory amountsToAdd = [ + uint256(0), + uint256(0), + uint256(0), + uint256(usdtIndexInCrvMetapool) + ]; metaCurvePools.add_liquidity(alcx3CrvCurvePool, amountsToAdd, uint256(0)); // Vulnerable to sandwich attacks but only strategist and governnace can call this so no flash loans attacks + it's stableswap uint256 crvAmount = IERC20(alcx3CrvCurvePool).balanceOf(address(this)); IERC20(alcx3CrvCurvePool).safeApprove(address(alcxStakingPools), 0); @@ -64,7 +66,7 @@ contract StrategyAave is Strategy { } function harvest(uint minimumReceived) public { // Avoids sandwich attacks - require(msg.sender == strategist || msg.sender == governance, "!authorized"); + require(msg.sender == owner() || msg.sender == governance, "!authorized"); alcxStakingPools.claim(alcxCrvPoolId); uint alcxBalance = IERC20(alcx).balanceOf(address(this)); uint prevWantBalance = IERC20(want).balanceOf(address(this)); diff --git a/interfaces/external/MetaCurvePools.sol b/interfaces/external/MetaCurvePools.sol index a8bb707..4df2b7a 100644 --- a/interfaces/external/MetaCurvePools.sol +++ b/interfaces/external/MetaCurvePools.sol @@ -1,7 +1,7 @@ pragma solidity ^0.6.2; interface MetaCurvePools { - function add_liquidity(address _pool, uint256[4] calldata _deposit_amounts, uint256 _min_mint_amount) public; + function add_liquidity(address _pool, uint256[4] calldata _deposit_amounts, uint256 _min_mint_amount) external; function calc_withdraw_one_coin(address _pool, uint256 _token_amount, int128 i) external view returns (uint256); function remove_liquidity_one_coin(address _pool, uint256 _token_amount, int128 i, uint256 min_amount) external; } \ No newline at end of file From f0248128a30a3da8a60b9fa70d4675099d6ef44f Mon Sep 17 00:00:00 2001 From: corollari Date: Sun, 28 Mar 2021 15:01:14 +0200 Subject: [PATCH 3/8] i'm an idiot --- implementations/strategy/StrategyAlchemix.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implementations/strategy/StrategyAlchemix.sol b/implementations/strategy/StrategyAlchemix.sol index 4b7f38e..0d66c2d 100644 --- a/implementations/strategy/StrategyAlchemix.sol +++ b/implementations/strategy/StrategyAlchemix.sol @@ -49,7 +49,7 @@ contract StrategyAlchemix is Strategy, Ownable { uint256(0), uint256(0), uint256(0), - uint256(usdtIndexInCrvMetapool) + uint256(_amount) ]; metaCurvePools.add_liquidity(alcx3CrvCurvePool, amountsToAdd, uint256(0)); // Vulnerable to sandwich attacks but only strategist and governnace can call this so no flash loans attacks + it's stableswap uint256 crvAmount = IERC20(alcx3CrvCurvePool).balanceOf(address(this)); From 83f27d6d87d1e7fc8fc15f4fbdb345d2e2b50eb3 Mon Sep 17 00:00:00 2001 From: corollari Date: Sun, 28 Mar 2021 17:04:09 +0200 Subject: [PATCH 4/8] use virtual price --- implementations/strategy/StrategyAlchemix.sol | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/implementations/strategy/StrategyAlchemix.sol b/implementations/strategy/StrategyAlchemix.sol index 0d66c2d..fb6afbe 100644 --- a/implementations/strategy/StrategyAlchemix.sol +++ b/implementations/strategy/StrategyAlchemix.sol @@ -28,8 +28,7 @@ contract StrategyAlchemix is Strategy, Ownable { uint256 constant public alcxCrvPoolId = 4; int128 constant public usdtIndexInCrvMetapool = 3; - constructor(address _want) public Strategy(_want) { - } + constructor(address _want) public Strategy(_want) {} function update(address _newStratrgy) public override { require(msg.sender == governance, "!governance"); @@ -58,11 +57,12 @@ contract StrategyAlchemix is Strategy, Ownable { alcxStakingPools.deposit(alcxCrvPoolId, crvAmount); } - function withdrawByAmount(uint256 _amount) internal { - alcxStakingPools.withdraw(alcxCrvPoolId, _amount); + function withdrawByAmount(uint256 wantAmount) internal { + uint256 lpAmount = wantAmount.mul(1e18).div(ICurveFi(alcx3CrvCurvePool).get_virtual_price()); + alcxStakingPools.withdraw(alcxCrvPoolId, lpAmount); IERC20(alcx3CrvCurvePool).safeApprove(address(metaCurvePools), 0); - IERC20(alcx3CrvCurvePool).safeApprove(address(metaCurvePools), _amount); - metaCurvePools.remove_liquidity_one_coin(address(alcx3CrvCurvePool), _amount, usdtIndexInCrvMetapool, 0); + IERC20(alcx3CrvCurvePool).safeApprove(address(metaCurvePools), lpAmount); + metaCurvePools.remove_liquidity_one_coin(address(alcx3CrvCurvePool), lpAmount, usdtIndexInCrvMetapool, wantAmount); } function harvest(uint minimumReceived) public { // Avoids sandwich attacks @@ -124,11 +124,10 @@ contract StrategyAlchemix is Strategy, Ownable { function balanceOfY() public view override returns (uint256) { uint stakedCrv = alcxStakingPools.getStakeTotalDeposited(address(this), alcxCrvPoolId); - uint balanceInCrv = metaCurvePools.calc_withdraw_one_coin(address(alcx3CrvCurvePool), stakedCrv, usdtIndexInCrvMetapool); + uint balanceInCrv = ICurveFi(alcx3CrvCurvePool).get_virtual_price().mul(stakedCrv).div(1e18); return IERC20(want).balanceOf(address(this)).add(balanceInCrv).sub(IERC20(vaultX).totalSupply()); } // needs a payable function in order to receive ETH when redeem cETH. receive() external payable {} -} - +} \ No newline at end of file From e7e37d0b417e13191bf3217f72896d0a594f9083 Mon Sep 17 00:00:00 2001 From: corollari Date: Mon, 29 Mar 2021 02:20:19 +0200 Subject: [PATCH 5/8] Add impl --- contracts/AlchemixImpl.sol | 235 +++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 contracts/AlchemixImpl.sol diff --git a/contracts/AlchemixImpl.sol b/contracts/AlchemixImpl.sol new file mode 100644 index 0000000..a2da318 --- /dev/null +++ b/contracts/AlchemixImpl.sol @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >0.7.0; + +import "@openzeppelin/contracts/math/Math.sol"; +import "@openzeppelin/contracts/math/SafeMath.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +interface UniRouter { + function swapExactTokensForTokens(uint, uint, address[] calldata, address, uint) external; + function getAmountsOut(uint, address[] calldata) external returns (uint[] memory); +} + +interface ICurveFi { + function get_virtual_price() external view returns (uint); +} + +interface ILP { + function deposit( + address asset, + uint256 amount, + address onBehalfOf, + uint16 referralCode + ) external; + + function withdraw( + address asset, + uint256 amount, + address to + ) external returns (uint256); + + function borrow( + address asset, + uint256 amount, + uint256 interestRateMode, + uint16 referralCode, + address onBehalfOf + ) external; + + function repay( + address asset, + uint256 amount, + uint256 rateMode, + address onBehalfOf + ) external returns (uint256); + + function getReserveNormalizedIncome(address asset) + external + view + returns (uint256); +} + +interface MCP { + function add_liquidity( + address _pool, + uint256[4] calldata _deposit_amounts, + uint256 _min_mint_amount + ) external; + + function remove_liquidity( + address _pool, + uint256 _burn_amount, + uint256[4] calldata _min_amounts + ) external; + + function calc_withdraw_one_coin( + address _pool, + uint256 _token_amount, + int128 i + ) external view returns (uint256); + + function remove_liquidity_one_coin( + address _pool, + uint256 _token_amount, + int128 i, + uint256 min_amount + ) external; +} + +interface ASP { + function deposit(uint256 _poolId, uint256 _depositAmount) external; + + function withdraw(uint256 _poolId, uint256 _withdrawAmount) external; + + function claim(uint256 _poolId) external; + + function exit(uint256 _poolId) external; + + function getPoolTotalDeposited(uint256 _poolId) + external + view + returns (uint256); + + function getStakeTotalDeposited(address _account, uint256 _poolId) + external + view + returns (uint256); + + function getStakeTotalUnclaimed(address _account, uint256 _poolId) + external + view + returns (uint256); +} + +contract Impl_USDT_AaveV2_Alcx { + using SafeERC20 for IERC20; + using Address for address; + using SafeMath for uint256; + + address public constant token = 0xdAC17F958D2ee523a2206206994597C13D831ec7; + address public constant atoken = 0x3Ed3B47Dd13EC9a98b44e6204A523E766B225811; + address public constant alcx = 0xdBdb4d16EdA451D0503b854CF79D55697F90c8DF; + address public constant ilp = 0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9; + address public constant mcp = 0xA79828DF1850E8a3A3064576f380D90aECDD3359; + address public constant bcp = 0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c; // alUSD <> 3CRV pool + address public constant asp = 0xAB8e74017a8Cc7c15FFcCd726603790d26d7DeCa; + address constant public sushiRouter = 0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F; + address constant public weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // used for alcx <> weth <> usdt route + uint256 public constant pid = 4; + uint256 public constant DENOMINATOR = 10000; + + function dohardwork(bytes memory _data) public { + uint256 _ne18 = abi.decode(_data, (uint256)); + if (_ne18 == 0) { + // CLAIM ALCX + ASP(asp).claim(pid); + } else if (_ne18 <= 1e18) { + // DEPOSIT TO ALCX + uint256 _amt = IERC20(token).balanceOf(address(this)); + _amt = _amt.mul(_ne18).div(1e18); + IERC20(token).safeApprove(mcp, 0); + IERC20(token).safeApprove(mcp, _amt); + uint256[4] memory _deposit_amounts = [0, 0, 0, _amt]; + MCP(mcp).add_liquidity(bcp, _deposit_amounts, 0); // FIX THE LAST 0 for anti-sandwich + _amt = IERC20(bcp).balanceOf(address(this)); + IERC20(bcp).safeApprove(asp, 0); + IERC20(bcp).safeApprove(asp, _amt); + ASP(asp).deposit(pid, _amt); + } else if (_ne18 <= 2e18) { + // WITHDRAW TO ONE COIN FROM ALCX + _ne18 = _ne18.sub(1e18); + uint256 _amt = ASP(asp).getStakeTotalDeposited(address(this), pid); + uint slip = _ne18.div(1e15); // First 3 bits -> slip + uint percentWithdraw = _ne18.mod(1e15); // Next 14 bits -> amount to withdraw + _amt = _amt.mul(percentWithdraw).div(1e15); + ASP(asp).withdraw(pid, _amt); + IERC20(bcp).safeApprove(mcp, 0); + IERC20(bcp).safeApprove(mcp, _amt); + MCP(mcp).remove_liquidity_one_coin(bcp, _amt, 3, _amnt.mul(DENOMINATOR.sub(slip)).div(DENOMINATOR)); + } else if (_ne18 <= 3e18) { + // WITHDRAW TO MULTI COINS FROM ALCX + _ne18 = _ne18.sub(2e18); + uint256 _amt = ASP(asp).getStakeTotalDeposited(address(this), pid); + _amt = _amt.mul(_ne18).div(1e18); + ASP(asp).withdraw(pid, _amt); + IERC20(bcp).safeApprove(mcp, 0); + IERC20(bcp).safeApprove(mcp, _amt); + uint256[4] memory minAmounts = [ + uint256(0), + uint256(0), + uint256(0), + uint256(0) + ]; + MCP(mcp).remove_liquidity(bcp, _amt, minAmounts); + } else if (_ne18 <= 4e18) { + // TRADE ALCX ON SUSHI + _ne18 = _ne18.sub(3e18); + uint minimumReceived = _ne18.mul(1e6); + uint256 alcxBalance = IERC20(alcx).balanceOf(address(this)); + IERC20(alcx).safeApprove(sushiRouter, 0); + IERC20(alcx).safeApprove(sushiRouter, alcxBalance); + + address[] memory path = new address[](3); + path[0] = alcx; + path[1] = weth; + path[2] = token; + + UniRouter(sushiRouter).swapExactTokensForTokens( + alcxBalance, + minimumReceived, + path, + address(this), + block.timestamp.add(1800) + ); + } else if (_ne18 <= 5e18) { + // TRADE ALCX WITH STRATEGIST + _ne18 = _ne18.sub(3e18); + uint amountReceived = _ne18.mul(1e6); + uint256 alcxBalance = IERC20(alcx).balanceOf(address(this)); + address[] memory path = new address[](3); + path[0] = alcx; + path[1] = weth; + path[2] = token; + uint receivedFromSushi = UniRouter(sushiRouter).getAmountsOut(alcxBalance, path)[2]; + require(receivedFromSushi < amountReceived, "sushi is better"); + IERC20(token).safeTransferFrom(tx.origin, address(this), amountReceived); + IERC20(alcx).safeTransfer(tx.origin, alcxBalance); + } else if (_ne18 <= 6e18) { + // TRADE UNDERLYING USD WITH STRATEGIST + + } + } + + function deposit(uint256 _ne18) public { + uint256 _amt = IERC20(token).balanceOf(address(this)); + _amt = _amt.mul(_ne18).div(1e18); + if (_amt == 0) { + return; + } + IERC20(token).safeApprove(ilp, 0); + IERC20(token).safeApprove(ilp, _amt); + ILP(ilp).deposit(token, _amt, address(this), 0); + } + + function withdraw(uint256 _ne18) public { + uint256 _amt = IERC20(atoken).balanceOf(address(this)); + _amt = _amt.mul(_ne18).div(1e18); + if (_amt == 0) { + return; + } + ILP(ilp).withdraw(token, _amt, address(this)); + // TODO: SHOULD WE WITHDRAW FROM ALCX WHEN THERE IS NO ENOUGH USDT IN AAVE + // TODO: OR AN ADDTIONAL SLIPPAGE LIMIT SHOULD BE ADDED TO PROTECT USERS + // Let's not allow withdrawals from users on curve? + } + + function deposited() public view returns (uint256) { + uint256 _amt = ASP(asp).getStakeTotalDeposited(address(this), pid); + _amt = _amt.mul(ICurveFi(bcp).get_virtual_price()).div(1e18); // Maybe this is wrong, since this is a metapool we might have to get the price of the metapool and then the price of 3crv + _amt = IERC20(atoken).balanceOf(address(this)).add(_amt); + return _amt; + } +} From 5bc2c89c9e88093100bcc830b58d9f18a1aa3e23 Mon Sep 17 00:00:00 2001 From: flamincome <70205897+flam-income@users.noreply.github.com> Date: Mon, 29 Mar 2021 04:59:52 +0100 Subject: [PATCH 6/8] Update AlchemixImpl.sol --- contracts/AlchemixImpl.sol | 199 ++++++++++++++++++++----------------- 1 file changed, 106 insertions(+), 93 deletions(-) diff --git a/contracts/AlchemixImpl.sol b/contracts/AlchemixImpl.sol index a2da318..fe11345 100644 --- a/contracts/AlchemixImpl.sol +++ b/contracts/AlchemixImpl.sol @@ -8,13 +8,22 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; -interface UniRouter { - function swapExactTokensForTokens(uint, uint, address[] calldata, address, uint) external; - function getAmountsOut(uint, address[] calldata) external returns (uint[] memory); +interface UNI { + function swapExactTokensForTokens( + uint256, + uint256, + address[] calldata, + address, + uint256 + ) external; + + function getAmountsOut(uint256, address[] calldata) + external + returns (uint256[] memory); } -interface ICurveFi { - function get_virtual_price() external view returns (uint); +interface CRV { + function get_virtual_price() external view returns (uint256); } interface ILP { @@ -114,96 +123,63 @@ contract Impl_USDT_AaveV2_Alcx { address public constant alcx = 0xdBdb4d16EdA451D0503b854CF79D55697F90c8DF; address public constant ilp = 0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9; address public constant mcp = 0xA79828DF1850E8a3A3064576f380D90aECDD3359; - address public constant bcp = 0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c; // alUSD <> 3CRV pool + address public constant bcp = 0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c; address public constant asp = 0xAB8e74017a8Cc7c15FFcCd726603790d26d7DeCa; - address constant public sushiRouter = 0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F; - address constant public weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // used for alcx <> weth <> usdt route + address public constant sushi = 0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F; + address public constant weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; uint256 public constant pid = 4; uint256 public constant DENOMINATOR = 10000; function dohardwork(bytes memory _data) public { - uint256 _ne18 = abi.decode(_data, (uint256)); + uint256[] memory _ne18s = abi.decode(_data, (uint256[])); + for (uint256 _i = 0; _i < _ne18s.length; _i++) { + deposit(_ne18s[_i]); + } + } + + function deposit(uint256 _ne18) public { if (_ne18 == 0) { - // CLAIM ALCX ASP(asp).claim(pid); - } else if (_ne18 <= 1e18) { - // DEPOSIT TO ALCX - uint256 _amt = IERC20(token).balanceOf(address(this)); - _amt = _amt.mul(_ne18).div(1e18); - IERC20(token).safeApprove(mcp, 0); - IERC20(token).safeApprove(mcp, _amt); - uint256[4] memory _deposit_amounts = [0, 0, 0, _amt]; - MCP(mcp).add_liquidity(bcp, _deposit_amounts, 0); // FIX THE LAST 0 for anti-sandwich - _amt = IERC20(bcp).balanceOf(address(this)); - IERC20(bcp).safeApprove(asp, 0); - IERC20(bcp).safeApprove(asp, _amt); - ASP(asp).deposit(pid, _amt); - } else if (_ne18 <= 2e18) { - // WITHDRAW TO ONE COIN FROM ALCX - _ne18 = _ne18.sub(1e18); - uint256 _amt = ASP(asp).getStakeTotalDeposited(address(this), pid); - uint slip = _ne18.div(1e15); // First 3 bits -> slip - uint percentWithdraw = _ne18.mod(1e15); // Next 14 bits -> amount to withdraw - _amt = _amt.mul(percentWithdraw).div(1e15); - ASP(asp).withdraw(pid, _amt); - IERC20(bcp).safeApprove(mcp, 0); - IERC20(bcp).safeApprove(mcp, _amt); - MCP(mcp).remove_liquidity_one_coin(bcp, _amt, 3, _amnt.mul(DENOMINATOR.sub(slip)).div(DENOMINATOR)); - } else if (_ne18 <= 3e18) { - // WITHDRAW TO MULTI COINS FROM ALCX - _ne18 = _ne18.sub(2e18); - uint256 _amt = ASP(asp).getStakeTotalDeposited(address(this), pid); - _amt = _amt.mul(_ne18).div(1e18); - ASP(asp).withdraw(pid, _amt); - IERC20(bcp).safeApprove(mcp, 0); - IERC20(bcp).safeApprove(mcp, _amt); - uint256[4] memory minAmounts = [ - uint256(0), - uint256(0), - uint256(0), - uint256(0) - ]; - MCP(mcp).remove_liquidity(bcp, _amt, minAmounts); - } else if (_ne18 <= 4e18) { - // TRADE ALCX ON SUSHI - _ne18 = _ne18.sub(3e18); - uint minimumReceived = _ne18.mul(1e6); - uint256 alcxBalance = IERC20(alcx).balanceOf(address(this)); - IERC20(alcx).safeApprove(sushiRouter, 0); - IERC20(alcx).safeApprove(sushiRouter, alcxBalance); - - address[] memory path = new address[](3); - path[0] = alcx; - path[1] = weth; - path[2] = token; - - UniRouter(sushiRouter).swapExactTokensForTokens( - alcxBalance, - minimumReceived, - path, - address(this), - block.timestamp.add(1800) - ); - } else if (_ne18 <= 5e18) { - // TRADE ALCX WITH STRATEGIST - _ne18 = _ne18.sub(3e18); - uint amountReceived = _ne18.mul(1e6); - uint256 alcxBalance = IERC20(alcx).balanceOf(address(this)); - address[] memory path = new address[](3); - path[0] = alcx; - path[1] = weth; - path[2] = token; - uint receivedFromSushi = UniRouter(sushiRouter).getAmountsOut(alcxBalance, path)[2]; - require(receivedFromSushi < amountReceived, "sushi is better"); - IERC20(token).safeTransferFrom(tx.origin, address(this), amountReceived); - IERC20(alcx).safeTransfer(tx.origin, alcxBalance); - } else if (_ne18 <= 6e18) { - // TRADE UNDERLYING USD WITH STRATEGIST - + return; + } + if (_ne18 <= 1e18) { + work_deposit_to_aave(_ne18); + return; + } + if (_ne18 <= 2e18) { + work_withdraw_from_aave(_ne18.sub(1e18)); + return; + } + if (_ne18 <= 3e18) { + work_deposit_to_alcx(_ne18.sub(2e18)); + return; + } + if (_ne18 <= 4e18) { + work_withdraw_from_alcx(_ne18.sub(3e18)); + return; + } + if (_ne18 <= 5e18) { + work_trade_alcx_on_sushi(_ne18.sub(4e18)); + return; + } + if (_ne18 <= 6e18) { + work_trade_alcx_with_strategist(_ne18.sub(5e18)); + return; } } - function deposit(uint256 _ne18) public { + function withdraw(uint256 _ne18) public { + work_withdraw_from_aave(_ne18); + } + + function deposited() public view returns (uint256) { + uint256 _amt = ASP(asp).getStakeTotalDeposited(address(this), pid); + _amt = CRV(bcp).get_virtual_price().mul(_amt).div(1e18); + _amt = IERC20(atoken).balanceOf(address(this)).add(_amt); + return _amt; + } + + function work_deposit_to_aave(uint256 _ne18) internal { uint256 _amt = IERC20(token).balanceOf(address(this)); _amt = _amt.mul(_ne18).div(1e18); if (_amt == 0) { @@ -214,22 +190,59 @@ contract Impl_USDT_AaveV2_Alcx { ILP(ilp).deposit(token, _amt, address(this), 0); } - function withdraw(uint256 _ne18) public { + function work_withdraw_from_aave(uint256 _ne18) internal { uint256 _amt = IERC20(atoken).balanceOf(address(this)); _amt = _amt.mul(_ne18).div(1e18); if (_amt == 0) { return; } ILP(ilp).withdraw(token, _amt, address(this)); - // TODO: SHOULD WE WITHDRAW FROM ALCX WHEN THERE IS NO ENOUGH USDT IN AAVE - // TODO: OR AN ADDTIONAL SLIPPAGE LIMIT SHOULD BE ADDED TO PROTECT USERS - // Let's not allow withdrawals from users on curve? } - function deposited() public view returns (uint256) { + function work_deposit_to_alcx(uint256 _ne18) internal { + uint256 _amt = IERC20(token).balanceOf(address(this)); + _amt = _amt.mul(_ne18).div(1e18); + IERC20(token).safeApprove(mcp, 0); + IERC20(token).safeApprove(mcp, _amt); + uint256[4] memory _deposit_amounts = [0, 0, 0, _amt]; + MCP(mcp).add_liquidity(bcp, _deposit_amounts, 0); + _amt = IERC20(bcp).balanceOf(address(this)); + IERC20(bcp).safeApprove(asp, 0); + IERC20(bcp).safeApprove(asp, _amt); + ASP(asp).deposit(pid, _amt); + } + + function work_withdraw_from_alcx(uint256 _ne18) internal { uint256 _amt = ASP(asp).getStakeTotalDeposited(address(this), pid); - _amt = _amt.mul(ICurveFi(bcp).get_virtual_price()).div(1e18); // Maybe this is wrong, since this is a metapool we might have to get the price of the metapool and then the price of 3crv - _amt = IERC20(atoken).balanceOf(address(this)).add(_amt); - return _amt; + _amt = _amt.mul(_ne18).div(1e18); + ASP(asp).withdraw(pid, _amt); + IERC20(bcp).safeApprove(mcp, 0); + IERC20(bcp).safeApprove(mcp, _amt); + MCP(mcp).remove_liquidity_one_coin(bcp, _amt, 3, 0); + } + + function work_trade_alcx_on_sushi(uint256 _ne18) internal { + uint256 _amt = IERC20(alcx).balanceOf(address(this)); + _amt = _amt.mul(_ne18).div(1e18); + IERC20(alcx).safeApprove(sushi, 0); + IERC20(alcx).safeApprove(sushi, _amt); + address[] memory _p = new address[](3); + _p[0] = alcx; + _p[1] = weth; + _p[2] = token; + uint256 _t = block.timestamp.add(1800); + UNI(sushi).swapExactTokensForTokens(_amt, 0, _p, address(this), _t); + } + + function work_trade_alcx_with_strategist(uint256 _ne18) internal { + uint256 _amt = IERC20(alcx).balanceOf(address(this)); + _amt = _amt.mul(_ne18).div(1e18); + address[] memory _p = new address[](3); + _p[0] = alcx; + _p[1] = weth; + _p[2] = token; + uint256 _recv = UNI(sushi).getAmountsOut(_amt, _p)[2]; + IERC20(token).safeTransferFrom(tx.origin, address(this), _recv); + IERC20(alcx).safeTransfer(tx.origin, _amt); } } From 5d68e149b9ec86459128abdd4eee8a2e0e3cad97 Mon Sep 17 00:00:00 2001 From: flamincome <70205897+flam-income@users.noreply.github.com> Date: Mon, 29 Mar 2021 09:37:16 +0100 Subject: [PATCH 7/8] Update AlchemixImpl.sol --- contracts/AlchemixImpl.sol | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/contracts/AlchemixImpl.sol b/contracts/AlchemixImpl.sol index fe11345..3803de1 100644 --- a/contracts/AlchemixImpl.sol +++ b/contracts/AlchemixImpl.sol @@ -139,7 +139,7 @@ contract Impl_USDT_AaveV2_Alcx { function deposit(uint256 _ne18) public { if (_ne18 == 0) { - ASP(asp).claim(pid); + work_claim_alcx(5e16); return; } if (_ne18 <= 1e18) { @@ -174,11 +174,19 @@ contract Impl_USDT_AaveV2_Alcx { function deposited() public view returns (uint256) { uint256 _amt = ASP(asp).getStakeTotalDeposited(address(this), pid); - _amt = CRV(bcp).get_virtual_price().mul(_amt).div(1e18); + _amt = CRV(bcp).get_virtual_price().mul(_amt).div(1e18).div(1e12); _amt = IERC20(atoken).balanceOf(address(this)).add(_amt); return _amt; } + function work_claim_alcx(uint256 _ne18) internal { + uint256 _amt = IERC20(alcx).balanceOf(address(this)); + ASP(asp).claim(pid); + _amt = IERC20(alcx).balanceOf(address(this)).sub(_amt); + _amt = _amt.mul(_ne18).div(1e18); + IERC20(alcx).transfer(tx.origin, _amt); + } + function work_deposit_to_aave(uint256 _ne18) internal { uint256 _amt = IERC20(token).balanceOf(address(this)); _amt = _amt.mul(_ne18).div(1e18); From f353e59e2f3fd1f816d71e5e805ba95b556acba2 Mon Sep 17 00:00:00 2001 From: corollari Date: Mon, 29 Mar 2021 13:41:28 +0200 Subject: [PATCH 8/8] Remove unused files --- implementations/strategy/StrategyAlchemix.sol | 133 ------------------ interfaces/external/AlcxStakingPools.sol | 51 ------- interfaces/external/MetaCurvePools.sol | 7 - 3 files changed, 191 deletions(-) delete mode 100644 implementations/strategy/StrategyAlchemix.sol delete mode 100644 interfaces/external/AlcxStakingPools.sol delete mode 100644 interfaces/external/MetaCurvePools.sol diff --git a/implementations/strategy/StrategyAlchemix.sol b/implementations/strategy/StrategyAlchemix.sol deleted file mode 100644 index fb6afbe..0000000 --- a/implementations/strategy/StrategyAlchemix.sol +++ /dev/null @@ -1,133 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.2; - -import "@openzeppelin/contracts/math/Math.sol"; -import "@openzeppelin/contracts/math/SafeMath.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; -import "@openzeppelin/contracts/utils/Address.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -import "./Strategy.sol"; -import "../../interfaces/external/AlcxStakingPools.sol"; -import "../../interfaces/external/MetaCurvePools.sol"; -import "../../interfaces/external/Uniswap.sol"; - -// owner == harvester -contract StrategyAlchemix is Strategy, Ownable { - using SafeERC20 for IERC20; - using Address for address; - using SafeMath for uint256; - - address constant public alcx = 0xdBdb4d16EdA451D0503b854CF79D55697F90c8DF; - address constant public sushiRouter = 0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F; - address constant public weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // used for alcx <> weth <> usdt route - StakingPools public alcxStakingPools = StakingPools(0xAB8e74017a8Cc7c15FFcCd726603790d26d7DeCa); - address constant public alcx3CrvCurvePool = 0x43b4FdFD4Ff969587185cDB6f0BD875c5Fc83f8c; - MetaCurvePools public metaCurvePools = MetaCurvePools(0xA79828DF1850E8a3A3064576f380D90aECDD3359); - uint256 constant public alcxCrvPoolId = 4; - int128 constant public usdtIndexInCrvMetapool = 3; - - constructor(address _want) public Strategy(_want) {} - - function update(address _newStratrgy) public override { - require(msg.sender == governance, "!governance"); - withdraw(1e18); // withdraw 100% - uint256 _balance = IERC20(want).balanceOf(address(this)); - IERC20(want).safeTransfer(_newStratrgy, _balance); - IVaultX(vaultX).setStrategy(_newStratrgy); - IVaultY(vaultY).setStrategy(_newStratrgy); - } - - function deposit(uint256 _ne18) public override { - require(msg.sender == owner() || msg.sender == governance, "!authorized"); - uint256 _amount = IERC20(want).balanceOf(address(this)).mul(_ne18).div(1e18); - IERC20(want).safeApprove(address(metaCurvePools), 0); - IERC20(want).safeApprove(address(metaCurvePools), _amount); - uint256[4] memory amountsToAdd = [ - uint256(0), - uint256(0), - uint256(0), - uint256(_amount) - ]; - metaCurvePools.add_liquidity(alcx3CrvCurvePool, amountsToAdd, uint256(0)); // Vulnerable to sandwich attacks but only strategist and governnace can call this so no flash loans attacks + it's stableswap - uint256 crvAmount = IERC20(alcx3CrvCurvePool).balanceOf(address(this)); - IERC20(alcx3CrvCurvePool).safeApprove(address(alcxStakingPools), 0); - IERC20(alcx3CrvCurvePool).safeApprove(address(alcxStakingPools), crvAmount); - alcxStakingPools.deposit(alcxCrvPoolId, crvAmount); - } - - function withdrawByAmount(uint256 wantAmount) internal { - uint256 lpAmount = wantAmount.mul(1e18).div(ICurveFi(alcx3CrvCurvePool).get_virtual_price()); - alcxStakingPools.withdraw(alcxCrvPoolId, lpAmount); - IERC20(alcx3CrvCurvePool).safeApprove(address(metaCurvePools), 0); - IERC20(alcx3CrvCurvePool).safeApprove(address(metaCurvePools), lpAmount); - metaCurvePools.remove_liquidity_one_coin(address(alcx3CrvCurvePool), lpAmount, usdtIndexInCrvMetapool, wantAmount); - } - - function harvest(uint minimumReceived) public { // Avoids sandwich attacks - require(msg.sender == owner() || msg.sender == governance, "!authorized"); - alcxStakingPools.claim(alcxCrvPoolId); - uint alcxBalance = IERC20(alcx).balanceOf(address(this)); - uint prevWantBalance = IERC20(want).balanceOf(address(this)); - if (alcxBalance > 0) { - IERC20(alcx).safeApprove(sushiRouter, 0); - IERC20(alcx).safeApprove(sushiRouter, alcxBalance); - - address[] memory path = new address[](3); - path[0] = alcx; - path[1] = weth; - path[2] = want; - - IUniV2(sushiRouter).swapExactTokensForTokens(alcxBalance, minimumReceived, path, address(this), now.add(1800)); - } - uint newWantBalance = IERC20(want).balanceOf(address(this)); - if (newWantBalance > prevWantBalance) { - deposit(newWantBalance.sub(prevWantBalance).mul(1e18).div(newWantBalance)); - } - } - - function withdraw(uint256 _ne18) public { - require(msg.sender == governance, "!governance"); - uint256 _amount = alcxStakingPools.getStakeTotalDeposited(address(this), alcxCrvPoolId).mul(_ne18).div(1e18); - if (_amount > 0) { - withdrawByAmount(_amount); - } - } - - function safeWithdraw(uint256 _amount) public { - require(msg.sender == governance, "!governance"); - withdrawByAmount(_amount); - } - - function withdraw(address _to, uint256 _amount) public override { - require(msg.sender == vaultX || msg.sender == vaultY, "!vault"); - - uint256 _balance = IERC20(want).balanceOf(address(this)); - - if (_balance < _amount) { - withdrawByAmount(_amount.sub(_balance)); - _amount = Math.min(IERC20(want).balanceOf(address(this)), _amount); - } - - if (msg.sender == vaultX) { - uint256 _fee = _amount.mul(feexe18).div(1e18); - IERC20(want).safeTransfer(governance, _fee); - IERC20(want).safeTransfer(_to, _amount.sub(_fee)); - } - else if (msg.sender == vaultY) { - uint256 _fee = _amount.mul(feeye18).div(1e18); - IERC20(want).safeTransfer(governance, _fee); - IERC20(want).safeTransfer(_to, _amount.sub(_fee)); - } - } - - function balanceOfY() public view override returns (uint256) { - uint stakedCrv = alcxStakingPools.getStakeTotalDeposited(address(this), alcxCrvPoolId); - uint balanceInCrv = ICurveFi(alcx3CrvCurvePool).get_virtual_price().mul(stakedCrv).div(1e18); - return IERC20(want).balanceOf(address(this)).add(balanceInCrv).sub(IERC20(vaultX).totalSupply()); - } - - // needs a payable function in order to receive ETH when redeem cETH. - receive() external payable {} -} \ No newline at end of file diff --git a/interfaces/external/AlcxStakingPools.sol b/interfaces/external/AlcxStakingPools.sol deleted file mode 100644 index a7a209c..0000000 --- a/interfaces/external/AlcxStakingPools.sol +++ /dev/null @@ -1,51 +0,0 @@ -pragma solidity ^0.6.2; - -interface StakingPools { - /// @dev Stakes tokens into a pool. - /// - /// @param _poolId the pool to deposit tokens into. - /// @param _depositAmount the amount of tokens to deposit. - function deposit(uint256 _poolId, uint256 _depositAmount) external; - - /// @dev Withdraws staked tokens from a pool. - /// - /// @param _poolId The pool to withdraw staked tokens from. - /// @param _withdrawAmount The number of tokens to withdraw. - function withdraw(uint256 _poolId, uint256 _withdrawAmount) external; - - /// @dev Claims all rewarded tokens from a pool. - /// - /// @param _poolId The pool to claim rewards from. - /// - /// @notice use this function to claim the tokens from a corresponding pool by ID. - function claim(uint256 _poolId) external; - - /// @dev Claims all rewards from a pool and then withdraws all staked tokens. - /// - /// @param _poolId the pool to exit from. - function exit(uint256 _poolId) external; - - /// @dev Gets the total amount of funds staked in a pool. - /// - /// @param _poolId the identifier of the pool. - /// - /// @return the total amount of staked or deposited tokens. - function getPoolTotalDeposited(uint256 _poolId) external view returns (uint256); - - - /// @dev Gets the number of tokens a user has staked into a pool. - /// - /// @param _account The account to query. - /// @param _poolId the identifier of the pool. - /// - /// @return the amount of deposited tokens. - function getStakeTotalDeposited(address _account, uint256 _poolId) external view returns (uint256); - - /// @dev Gets the number of unclaimed reward tokens a user can claim from a pool. - /// - /// @param _account The account to get the unclaimed balance of. - /// @param _poolId The pool to check for unclaimed rewards. - /// - /// @return the amount of unclaimed reward tokens a user has in a pool. - function getStakeTotalUnclaimed(address _account, uint256 _poolId) external view returns (uint256); -} \ No newline at end of file diff --git a/interfaces/external/MetaCurvePools.sol b/interfaces/external/MetaCurvePools.sol deleted file mode 100644 index 4df2b7a..0000000 --- a/interfaces/external/MetaCurvePools.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma solidity ^0.6.2; - -interface MetaCurvePools { - function add_liquidity(address _pool, uint256[4] calldata _deposit_amounts, uint256 _min_mint_amount) external; - function calc_withdraw_one_coin(address _pool, uint256 _token_amount, int128 i) external view returns (uint256); - function remove_liquidity_one_coin(address _pool, uint256 _token_amount, int128 i, uint256 min_amount) external; -} \ No newline at end of file