mirror of
				https://github.com/Instadapp/dsa-connectors-old.git
				synced 2024-07-29 22:47:46 +00:00 
			
		
		
		
	fix formating on connectors/curve.sol;
adding @openzeppelin/test-helpers, ganache-cli; fixing test/CurveProtocol.js to pass; added truffle network for tenderly proxy; added .nvmrc to set to node v12 as ganache-cli requires;
This commit is contained in:
		
							parent
							
								
									076a836c03
								
							
						
					
					
						commit
						bce54aba13
					
				| 
						 | 
				
			
			@ -6,224 +6,223 @@ import { Stores } from "../common/stores.sol";
 | 
			
		|||
import { DSMath } from "../common/math.sol";
 | 
			
		||||
 | 
			
		||||
interface ICurve {
 | 
			
		||||
    function underlying_coins(int128 tokenId) external view returns (address token);
 | 
			
		||||
    function calc_token_amount(uint256[4] calldata amounts, bool deposit) external returns (uint256 amount);
 | 
			
		||||
    function add_liquidity(uint256[4] calldata amounts, uint256 min_mint_amount) external;
 | 
			
		||||
    function get_dy(int128 sellTokenId, int128 buyTokenId, uint256 sellTokenAmt) external returns (uint256 buyTokenAmt);
 | 
			
		||||
    function exchange(int128 sellTokenId, int128 buyTokenId, uint256 sellTokenAmt, uint256 minBuyToken) external;
 | 
			
		||||
    function remove_liquidity_imbalance(uint256[4] calldata amounts, uint256 max_burn_amount) external;
 | 
			
		||||
  function underlying_coins(int128 tokenId) external view returns (address token);
 | 
			
		||||
  function calc_token_amount(uint256[4] calldata amounts, bool deposit) external returns (uint256 amount);
 | 
			
		||||
  function add_liquidity(uint256[4] calldata amounts, uint256 min_mint_amount) external;
 | 
			
		||||
  function get_dy(int128 sellTokenId, int128 buyTokenId, uint256 sellTokenAmt) external returns (uint256 buyTokenAmt);
 | 
			
		||||
  function exchange(int128 sellTokenId, int128 buyTokenId, uint256 sellTokenAmt, uint256 minBuyToken) external;
 | 
			
		||||
  function remove_liquidity_imbalance(uint256[4] calldata amounts, uint256 max_burn_amount) external;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface ICurveZap {
 | 
			
		||||
    function calc_withdraw_one_coin(uint256 _token_amount, int128 i) external returns (uint256 amount);
 | 
			
		||||
  function calc_withdraw_one_coin(uint256 _token_amount, int128 i) external returns (uint256 amount);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract CurveHelpers is Stores, DSMath {
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev Return Curve Swap Address
 | 
			
		||||
     */
 | 
			
		||||
    function getCurveSwapAddr() internal pure returns (address) {
 | 
			
		||||
        return 0xA5407eAE9Ba41422680e2e00537571bcC53efBfD;
 | 
			
		||||
    }
 | 
			
		||||
  /**
 | 
			
		||||
  * @dev Return Curve Swap Address
 | 
			
		||||
  */
 | 
			
		||||
  function getCurveSwapAddr() internal pure returns (address) {
 | 
			
		||||
    return 0xA5407eAE9Ba41422680e2e00537571bcC53efBfD;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev Return Curve Token Address
 | 
			
		||||
     */
 | 
			
		||||
    function getCurveTokenAddr() internal pure returns (address) {
 | 
			
		||||
        return 0xC25a3A3b969415c80451098fa907EC722572917F;
 | 
			
		||||
    }
 | 
			
		||||
  /**
 | 
			
		||||
  * @dev Return Curve Token Address
 | 
			
		||||
  */
 | 
			
		||||
  function getCurveTokenAddr() internal pure returns (address) {
 | 
			
		||||
    return 0xC25a3A3b969415c80451098fa907EC722572917F;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev Return Curve Zap Address
 | 
			
		||||
     */
 | 
			
		||||
    function getCurveZapAddr() internal pure returns (address) {
 | 
			
		||||
        return 0xFCBa3E75865d2d561BE8D220616520c171F12851;
 | 
			
		||||
    }
 | 
			
		||||
  /**
 | 
			
		||||
  * @dev Return Curve Zap Address
 | 
			
		||||
  */
 | 
			
		||||
  function getCurveZapAddr() internal pure returns (address) {
 | 
			
		||||
    return 0xFCBa3E75865d2d561BE8D220616520c171F12851;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    function convert18ToDec(uint _dec, uint256 _amt) internal pure returns (uint256 amt) {
 | 
			
		||||
        amt = (_amt / 10 ** (18 - _dec));
 | 
			
		||||
    }
 | 
			
		||||
  function convert18ToDec(uint _dec, uint256 _amt) internal pure returns (uint256 amt) {
 | 
			
		||||
    amt = (_amt / 10 ** (18 - _dec));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    function convertTo18(uint _dec, uint256 _amt) internal pure returns (uint256 amt) {
 | 
			
		||||
        amt = mul(_amt, 10 ** (18 - _dec));
 | 
			
		||||
    }
 | 
			
		||||
  function convertTo18(uint _dec, uint256 _amt) internal pure returns (uint256 amt) {
 | 
			
		||||
    amt = mul(_amt, 10 ** (18 - _dec));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    function getTokenI(address token) internal pure returns (int128 i) {
 | 
			
		||||
        if (token == address(0x6B175474E89094C44Da98b954EedeAC495271d0F)) {
 | 
			
		||||
            // DAI Token
 | 
			
		||||
            i = 0;
 | 
			
		||||
        } else if (token == address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48)) {
 | 
			
		||||
            // USDC Token
 | 
			
		||||
            i = 1;
 | 
			
		||||
        } else if (token == address(0xdAC17F958D2ee523a2206206994597C13D831ec7)) {
 | 
			
		||||
            // USDT Token
 | 
			
		||||
            i = 2;
 | 
			
		||||
        } else if (token == address(0x57Ab1ec28D129707052df4dF418D58a2D46d5f51)) {
 | 
			
		||||
            // sUSD Token
 | 
			
		||||
            i = 3;
 | 
			
		||||
        } else {
 | 
			
		||||
            revert("token-not-found.");
 | 
			
		||||
        }
 | 
			
		||||
  function getTokenI(address token) internal pure returns (int128 i) {
 | 
			
		||||
    if (token == address(0x6B175474E89094C44Da98b954EedeAC495271d0F)) {
 | 
			
		||||
      // DAI Token
 | 
			
		||||
      i = 0;
 | 
			
		||||
    } else if (token == address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48)) {
 | 
			
		||||
      // USDC Token
 | 
			
		||||
      i = 1;
 | 
			
		||||
    } else if (token == address(0xdAC17F958D2ee523a2206206994597C13D831ec7)) {
 | 
			
		||||
      // USDT Token
 | 
			
		||||
      i = 2;
 | 
			
		||||
    } else if (token == address(0x57Ab1ec28D129707052df4dF418D58a2D46d5f51)) {
 | 
			
		||||
      // sUSD Token
 | 
			
		||||
      i = 3;
 | 
			
		||||
    } else {
 | 
			
		||||
      revert("token-not-found.");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    function getTokenAddr(ICurve curve, uint256 i) internal view returns (address token) {
 | 
			
		||||
        token = curve.underlying_coins(int128(i));
 | 
			
		||||
        require(token != address(0), "token-not-found.");
 | 
			
		||||
    }
 | 
			
		||||
  function getTokenAddr(ICurve curve, uint256 i) internal view returns (address token) {
 | 
			
		||||
    token = curve.underlying_coins(int128(i));
 | 
			
		||||
    require(token != address(0), "token-not-found.");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract CurveProtocol is CurveHelpers {
 | 
			
		||||
 | 
			
		||||
     event LogSell(
 | 
			
		||||
        address indexed buyToken,
 | 
			
		||||
        address indexed sellToken,
 | 
			
		||||
        uint256 buyAmt,
 | 
			
		||||
        uint256 sellAmt,
 | 
			
		||||
        uint256 getId,
 | 
			
		||||
        uint256 setId
 | 
			
		||||
    );
 | 
			
		||||
    event LogDeposit(address token, uint256 amt, uint256 mintAmt, uint256 getId, uint256 setId);
 | 
			
		||||
    event LogWithdraw(address token, uint256 amt, uint256 burnAmt, uint256 getId,  uint256 setId);
 | 
			
		||||
  event LogSell(
 | 
			
		||||
    address indexed buyToken,
 | 
			
		||||
    address indexed sellToken,
 | 
			
		||||
    uint256 buyAmt,
 | 
			
		||||
    uint256 sellAmt,
 | 
			
		||||
    uint256 getId,
 | 
			
		||||
    uint256 setId
 | 
			
		||||
  );
 | 
			
		||||
  event LogDeposit(address token, uint256 amt, uint256 mintAmt, uint256 getId, uint256 setId);
 | 
			
		||||
  event LogWithdraw(address token, uint256 amt, uint256 burnAmt, uint256 getId,  uint256 setId);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev Sell Stable ERC20_Token.
 | 
			
		||||
     * @param buyAddr buying token address.
 | 
			
		||||
     * @param sellAddr selling token amount.
 | 
			
		||||
     * @param sellAmt selling token amount.
 | 
			
		||||
     * @param unitAmt unit amount of buyAmt/sellAmt with slippage.
 | 
			
		||||
     * @param getId Get token amount at this ID from `InstaMemory` Contract.
 | 
			
		||||
     * @param setId Set token amount at this ID in `InstaMemory` Contract.
 | 
			
		||||
  /**
 | 
			
		||||
  * @dev Sell Stable ERC20_Token.
 | 
			
		||||
  * @param buyAddr buying token address.
 | 
			
		||||
    * @param sellAddr selling token amount.
 | 
			
		||||
    * @param sellAmt selling token amount.
 | 
			
		||||
    * @param unitAmt unit amount of buyAmt/sellAmt with slippage.
 | 
			
		||||
    * @param getId Get token amount at this ID from `InstaMemory` Contract.
 | 
			
		||||
    * @param setId Set token amount at this ID in `InstaMemory` Contract.
 | 
			
		||||
    */
 | 
			
		||||
    function sell(
 | 
			
		||||
        address buyAddr,
 | 
			
		||||
        address sellAddr,
 | 
			
		||||
        uint sellAmt,
 | 
			
		||||
        uint unitAmt,
 | 
			
		||||
        uint getId,
 | 
			
		||||
        uint setId
 | 
			
		||||
    ) external payable {
 | 
			
		||||
        uint _sellAmt = getUint(getId, sellAmt);
 | 
			
		||||
        ICurve curve = ICurve(getCurveSwapAddr());
 | 
			
		||||
        TokenInterface _buyToken = TokenInterface(buyAddr);
 | 
			
		||||
        TokenInterface _sellToken = TokenInterface(sellAddr);
 | 
			
		||||
        _sellAmt = _sellAmt == uint(-1) ? _sellToken.balanceOf(address(this)) : _sellAmt;
 | 
			
		||||
        _sellToken.approve(address(curve), _sellAmt);
 | 
			
		||||
  function sell(
 | 
			
		||||
    address buyAddr,
 | 
			
		||||
    address sellAddr,
 | 
			
		||||
    uint sellAmt,
 | 
			
		||||
    uint unitAmt,
 | 
			
		||||
    uint getId,
 | 
			
		||||
    uint setId
 | 
			
		||||
  ) external payable {
 | 
			
		||||
    uint _sellAmt = getUint(getId, sellAmt);
 | 
			
		||||
    ICurve curve = ICurve(getCurveSwapAddr());
 | 
			
		||||
    TokenInterface _buyToken = TokenInterface(buyAddr);
 | 
			
		||||
    TokenInterface _sellToken = TokenInterface(sellAddr);
 | 
			
		||||
    _sellAmt = _sellAmt == uint(-1) ? _sellToken.balanceOf(address(this)) : _sellAmt;
 | 
			
		||||
    _sellToken.approve(address(curve), _sellAmt);
 | 
			
		||||
 | 
			
		||||
        uint _slippageAmt = convert18ToDec(_buyToken.decimals(), wmul(unitAmt, convertTo18(_sellToken.decimals(), _sellAmt)));
 | 
			
		||||
    uint _slippageAmt = convert18ToDec(_buyToken.decimals(), wmul(unitAmt, convertTo18(_sellToken.decimals(), _sellAmt)));
 | 
			
		||||
 | 
			
		||||
        uint intialBal = _buyToken.balanceOf(address(this));
 | 
			
		||||
        curve.exchange(getTokenI(sellAddr), getTokenI(buyAddr), _sellAmt, _slippageAmt);
 | 
			
		||||
        uint finalBal = _buyToken.balanceOf(address(this));
 | 
			
		||||
    uint intialBal = _buyToken.balanceOf(address(this));
 | 
			
		||||
    curve.exchange(getTokenI(sellAddr), getTokenI(buyAddr), _sellAmt, _slippageAmt);
 | 
			
		||||
    uint finalBal = _buyToken.balanceOf(address(this));
 | 
			
		||||
 | 
			
		||||
        uint _buyAmt = sub(finalBal, intialBal);
 | 
			
		||||
    uint _buyAmt = sub(finalBal, intialBal);
 | 
			
		||||
 | 
			
		||||
        setUint(setId, _buyAmt);
 | 
			
		||||
    setUint(setId, _buyAmt);
 | 
			
		||||
 | 
			
		||||
        emit LogSell(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId);
 | 
			
		||||
        bytes32 _eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)");
 | 
			
		||||
        bytes memory _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId);
 | 
			
		||||
        emitEvent(_eventCode, _eventParam);
 | 
			
		||||
    emit LogSell(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId);
 | 
			
		||||
    bytes32 _eventCode = keccak256("LogSell(address,address,uint256,uint256,uint256,uint256)");
 | 
			
		||||
    bytes memory _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId);
 | 
			
		||||
    emitEvent(_eventCode, _eventParam);
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
  * @dev Deposit Token.
 | 
			
		||||
  * @param token token address.
 | 
			
		||||
    * @param amt token amount.
 | 
			
		||||
    * @param unitAmt unit amount of curve_amt/token_amt with slippage.
 | 
			
		||||
    * @param getId Get token amount at this ID from `InstaMemory` Contract.
 | 
			
		||||
    * @param setId Set token amount at this ID in `InstaMemory` Contract.
 | 
			
		||||
    */
 | 
			
		||||
  function deposit(
 | 
			
		||||
    address token,
 | 
			
		||||
    uint amt,
 | 
			
		||||
    uint unitAmt,
 | 
			
		||||
    uint getId,
 | 
			
		||||
    uint setId
 | 
			
		||||
  ) external payable {
 | 
			
		||||
    uint256 _amt = getUint(getId, amt);
 | 
			
		||||
    TokenInterface tokenContract = TokenInterface(token);
 | 
			
		||||
 | 
			
		||||
    _amt = _amt == uint(-1) ? tokenContract.balanceOf(address(this)) : _amt;
 | 
			
		||||
    uint[4] memory _amts;
 | 
			
		||||
    _amts[uint(getTokenI(token))] = _amt;
 | 
			
		||||
 | 
			
		||||
    tokenContract.approve(getCurveSwapAddr(), _amt);
 | 
			
		||||
 | 
			
		||||
    uint _amt18 = convertTo18(tokenContract.decimals(), _amt);
 | 
			
		||||
    uint _slippageAmt = wmul(unitAmt, _amt18);
 | 
			
		||||
 | 
			
		||||
    TokenInterface curveTokenContract = TokenInterface(getCurveTokenAddr());
 | 
			
		||||
    uint initialCurveBal = curveTokenContract.balanceOf(address(this));
 | 
			
		||||
 | 
			
		||||
    ICurve(getCurveSwapAddr()).add_liquidity(_amts, _slippageAmt);
 | 
			
		||||
 | 
			
		||||
    uint finalCurveBal = curveTokenContract.balanceOf(address(this));
 | 
			
		||||
 | 
			
		||||
    uint mintAmt = sub(finalCurveBal, initialCurveBal);
 | 
			
		||||
 | 
			
		||||
    setUint(setId, mintAmt);
 | 
			
		||||
 | 
			
		||||
    emit LogDeposit(token, _amt, mintAmt, getId, setId);
 | 
			
		||||
    bytes32 _eventCode = keccak256("LogDeposit(address,uint256,uint256,uint256,uint256)");
 | 
			
		||||
    bytes memory _eventParam = abi.encode(token, _amt, mintAmt, getId, setId);
 | 
			
		||||
    emitEvent(_eventCode, _eventParam);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
  * @dev Withdraw Token.
 | 
			
		||||
  * @param token token address.
 | 
			
		||||
    * @param amt token amount.
 | 
			
		||||
    * @param unitAmt unit amount of curve_amt/token_amt with slippage.
 | 
			
		||||
    * @param getId Get token amount at this ID from `InstaMemory` Contract.
 | 
			
		||||
    * @param setId Set token amount at this ID in `InstaMemory` Contract.
 | 
			
		||||
    */
 | 
			
		||||
  function withdraw(
 | 
			
		||||
    address token,
 | 
			
		||||
    uint256 amt,
 | 
			
		||||
    uint256 unitAmt,
 | 
			
		||||
    uint getId,
 | 
			
		||||
    uint setId
 | 
			
		||||
  ) external payable {
 | 
			
		||||
    uint _amt = getUint(getId, amt);
 | 
			
		||||
    int128 tokenId = getTokenI(token);
 | 
			
		||||
 | 
			
		||||
    TokenInterface curveTokenContract = TokenInterface(getCurveTokenAddr());
 | 
			
		||||
    ICurveZap curveZap = ICurveZap(getCurveZapAddr());
 | 
			
		||||
    ICurve curveSwap = ICurve(getCurveSwapAddr());
 | 
			
		||||
 | 
			
		||||
    uint _curveAmt;
 | 
			
		||||
    uint[4] memory _amts;
 | 
			
		||||
    if (_amt == uint(-1)) {
 | 
			
		||||
      _curveAmt = curveTokenContract.balanceOf(address(this));
 | 
			
		||||
      _amt = curveZap.calc_withdraw_one_coin(_curveAmt, tokenId);
 | 
			
		||||
      _amts[uint(tokenId)] = _amt;
 | 
			
		||||
    } else {
 | 
			
		||||
      _amts[uint(tokenId)] = _amt;
 | 
			
		||||
      _curveAmt = curveSwap.calc_token_amount(_amts, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev Deposit Token.
 | 
			
		||||
     * @param token token address.
 | 
			
		||||
     * @param amt token amount.
 | 
			
		||||
     * @param unitAmt unit amount of curve_amt/token_amt with slippage.
 | 
			
		||||
     * @param getId Get token amount at this ID from `InstaMemory` Contract.
 | 
			
		||||
     * @param setId Set token amount at this ID in `InstaMemory` Contract.
 | 
			
		||||
    */
 | 
			
		||||
    function deposit(
 | 
			
		||||
        address token,
 | 
			
		||||
        uint amt,
 | 
			
		||||
        uint unitAmt,
 | 
			
		||||
        uint getId,
 | 
			
		||||
        uint setId
 | 
			
		||||
    ) external payable {
 | 
			
		||||
        uint256 _amt = getUint(getId, amt);
 | 
			
		||||
        TokenInterface tokenContract = TokenInterface(token);
 | 
			
		||||
 | 
			
		||||
        _amt = _amt == uint(-1) ? tokenContract.balanceOf(address(this)) : _amt;
 | 
			
		||||
        uint[4] memory _amts;
 | 
			
		||||
        _amts[uint(getTokenI(token))] = _amt;
 | 
			
		||||
    uint _amt18 = convertTo18(TokenInterface(token).decimals(), _amt);
 | 
			
		||||
    uint _slippageAmt = wmul(unitAmt, _amt18);
 | 
			
		||||
 | 
			
		||||
        tokenContract.approve(getCurveSwapAddr(), _amt);
 | 
			
		||||
    curveTokenContract.approve(address(curveSwap), 0);
 | 
			
		||||
    curveTokenContract.approve(address(curveSwap), _slippageAmt);
 | 
			
		||||
 | 
			
		||||
        uint _amt18 = convertTo18(tokenContract.decimals(), _amt);
 | 
			
		||||
        uint _slippageAmt = wmul(unitAmt, _amt18);
 | 
			
		||||
    curveSwap.remove_liquidity_imbalance(_amts, _slippageAmt);
 | 
			
		||||
 | 
			
		||||
        TokenInterface curveTokenContract = TokenInterface(getCurveTokenAddr());
 | 
			
		||||
        uint initialCurveBal = curveTokenContract.balanceOf(address(this));
 | 
			
		||||
    setUint(setId, _amt);
 | 
			
		||||
 | 
			
		||||
        ICurve(getCurveSwapAddr()).add_liquidity(_amts, _slippageAmt);
 | 
			
		||||
 | 
			
		||||
        uint finalCurveBal = curveTokenContract.balanceOf(address(this));
 | 
			
		||||
 | 
			
		||||
        uint mintAmt = sub(finalCurveBal, initialCurveBal);
 | 
			
		||||
 | 
			
		||||
        setUint(setId, mintAmt);
 | 
			
		||||
 | 
			
		||||
        emit LogDeposit(token, _amt, mintAmt, getId, setId);
 | 
			
		||||
        bytes32 _eventCode = keccak256("LogDeposit(address,uint256,uint256,uint256,uint256)");
 | 
			
		||||
        bytes memory _eventParam = abi.encode(token, _amt, mintAmt, getId, setId);
 | 
			
		||||
        emitEvent(_eventCode, _eventParam);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev Withdraw Token.
 | 
			
		||||
     * @param token token address.
 | 
			
		||||
     * @param amt token amount.
 | 
			
		||||
     * @param unitAmt unit amount of curve_amt/token_amt with slippage.
 | 
			
		||||
     * @param getId Get token amount at this ID from `InstaMemory` Contract.
 | 
			
		||||
     * @param setId Set token amount at this ID in `InstaMemory` Contract.
 | 
			
		||||
    */
 | 
			
		||||
    function withdraw(
 | 
			
		||||
        address token,
 | 
			
		||||
        uint256 amt,
 | 
			
		||||
        uint256 unitAmt,
 | 
			
		||||
        uint getId,
 | 
			
		||||
        uint setId
 | 
			
		||||
    ) external payable {
 | 
			
		||||
        uint _amt = getUint(getId, amt);
 | 
			
		||||
        int128 tokenId = getTokenI(token);
 | 
			
		||||
 | 
			
		||||
        TokenInterface curveTokenContract = TokenInterface(getCurveTokenAddr());
 | 
			
		||||
        ICurveZap curveZap = ICurveZap(getCurveZapAddr());
 | 
			
		||||
        ICurve curveSwap = ICurve(getCurveSwapAddr());
 | 
			
		||||
 | 
			
		||||
        uint _curveAmt;
 | 
			
		||||
        uint[4] memory _amts;
 | 
			
		||||
        if (_amt == uint(-1)) {
 | 
			
		||||
            _curveAmt = curveTokenContract.balanceOf(address(this));
 | 
			
		||||
            _amt = curveZap.calc_withdraw_one_coin(_curveAmt, tokenId);
 | 
			
		||||
            _amts[uint(tokenId)] = _amt;
 | 
			
		||||
        } else {
 | 
			
		||||
            _amts[uint(tokenId)] = _amt;
 | 
			
		||||
            _curveAmt = curveSwap.calc_token_amount(_amts, false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        uint _amt18 = convertTo18(TokenInterface(token).decimals(), _amt);
 | 
			
		||||
        uint _slippageAmt = wmul(unitAmt, _amt18);
 | 
			
		||||
 | 
			
		||||
        curveTokenContract.approve(address(curveSwap), 0);
 | 
			
		||||
        curveTokenContract.approve(address(curveSwap), _slippageAmt);
 | 
			
		||||
 | 
			
		||||
        curveSwap.remove_liquidity_imbalance(_amts, _slippageAmt);
 | 
			
		||||
 | 
			
		||||
        setUint(setId, _amt);
 | 
			
		||||
 | 
			
		||||
        emit LogWithdraw(token, _amt, _curveAmt, getId, setId);
 | 
			
		||||
        bytes32 _eventCode = keccak256("LogWithdraw(address,uint256,uint256,uint256,uint256)");
 | 
			
		||||
        bytes memory _eventParam = abi.encode(token, _amt, _curveAmt, getId, setId);
 | 
			
		||||
        emitEvent(_eventCode, _eventParam);
 | 
			
		||||
    }
 | 
			
		||||
    emit LogWithdraw(token, _amt, _curveAmt, getId, setId);
 | 
			
		||||
    bytes32 _eventCode = keccak256("LogWithdraw(address,uint256,uint256,uint256,uint256)");
 | 
			
		||||
    bytes memory _eventParam = abi.encode(token, _amt, _curveAmt, getId, setId);
 | 
			
		||||
    emitEvent(_eventCode, _eventParam);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
contract ConnectCurve is CurveProtocol {
 | 
			
		||||
    string public name = "Curve-susd-v1.2";
 | 
			
		||||
  string public name = "Curve-susd-v1.2";
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1669
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1669
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -5,10 +5,11 @@
 | 
			
		|||
  "main": "truffle-config.js",
 | 
			
		||||
  "directories": {},
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "test": "npm run ganache sleep 5 && truffle test && npm run stop",
 | 
			
		||||
    "test": "truffle test",
 | 
			
		||||
    "coverage": "./node_modules/.bin/solidity-coverage",
 | 
			
		||||
    "solium": "solium -d contracts/",
 | 
			
		||||
    "build-contracts": "sol-merger \"./contracts/connectors/mock.sol\" ./contracts/build"
 | 
			
		||||
    "build-contracts": "sol-merger \"./contracts/connectors/mock.sol\" ./contracts/build",
 | 
			
		||||
    "ganache": "ganache-cli --deterministic --unlock 0x9eb7f2591ed42dee9315b6e2aaf21ba85ea69f8c -f https://mainnet.infura.io/v3/<Your Key>"
 | 
			
		||||
  },
 | 
			
		||||
  "repository": {
 | 
			
		||||
    "type": "git",
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +36,8 @@
 | 
			
		|||
    "truffle-verify": "^1.0.8"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@openzeppelin/test-helpers": "^0.5.6",
 | 
			
		||||
    "ganache-cli": "^6.10.0-beta.2",
 | 
			
		||||
    "sol-merger": "^2.0.1",
 | 
			
		||||
    "solidity-coverage": "0.5.11",
 | 
			
		||||
    "solium": "1.2.3"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@ const CurveProtocol = artifacts.require('CurveProtocol')
 | 
			
		|||
const daiABI = require('./abi/dai');
 | 
			
		||||
const erc20 = require('./abi/erc20')
 | 
			
		||||
const swap_abi = require('./abi/swap')
 | 
			
		||||
const { ether, balance } = require('openzeppelin-test-helpers');
 | 
			
		||||
const { ether, balance } = require('@openzeppelin/test-helpers');
 | 
			
		||||
 | 
			
		||||
const BN = require('bn.js')
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -24,99 +24,106 @@ const swapContract = new web3.eth.Contract(swap_abi, swap)
 | 
			
		|||
const swapToken = '0xC25a3A3b969415c80451098fa907EC722572917F'
 | 
			
		||||
const tokenContract = new web3.eth.Contract(erc20, swapToken)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract('Curve Protocol', async accounts => {
 | 
			
		||||
 | 
			
		||||
  it('should send ether to the user address', async () => {
 | 
			
		||||
    let account = accounts[0]
 | 
			
		||||
    let contract = await CurveProtocol.deployed()
 | 
			
		||||
    const ethBalanceBefore = await balance.current(userAddress);
 | 
			
		||||
    // Send 0.1 eth to userAddress to have gas to send an ERC20 tx.
 | 
			
		||||
    await web3.eth.sendTransaction({
 | 
			
		||||
      from: accounts[0],
 | 
			
		||||
      to: userAddress,
 | 
			
		||||
      value: ether('0.1')
 | 
			
		||||
    });
 | 
			
		||||
    const ethBalanceAfter = await balance.current(userAddress);
 | 
			
		||||
    expect(+ethBalanceAfter - +ethBalanceBefore).to.equal(+ether('0.1'))
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
	it('should send ether to the DAI address', async () => {
 | 
			
		||||
		let account = accounts[0]
 | 
			
		||||
		let contract = await CurveProtocol.deployed()
 | 
			
		||||
		// Send 0.1 eth to userAddress to have gas to send an ERC20 tx.
 | 
			
		||||
		await web3.eth.sendTransaction({
 | 
			
		||||
		  from: accounts[0],
 | 
			
		||||
		  to: userAddress,
 | 
			
		||||
		  value: ether('0.1')
 | 
			
		||||
		});
 | 
			
		||||
		const ethBalance = await balance.current(userAddress);
 | 
			
		||||
		expect(+ethBalance).to.be.at.least(+ether('0.1'))
 | 
			
		||||
	});
 | 
			
		||||
  it('should transfer DAI to CurveProtocol', async () => {
 | 
			
		||||
    let account = accounts[0]
 | 
			
		||||
    let contract = await CurveProtocol.deployed()
 | 
			
		||||
    // Get 100 DAI for first 5 accounts
 | 
			
		||||
    // daiAddress is passed to ganache-cli with flag `--unlock`
 | 
			
		||||
    // so we can use the `transfer` method
 | 
			
		||||
    //
 | 
			
		||||
    // Note: This only works as userAddress has 2546221640728945323079640 Dai,
 | 
			
		||||
    // should remove this dependence in the future
 | 
			
		||||
    const daiBalanceUser = await daiContract.methods.balanceOf(userAddress).call();
 | 
			
		||||
    await daiContract.methods
 | 
			
		||||
      .transfer(contract.address, ether('100').toString())
 | 
			
		||||
      .send({ from: userAddress, gasLimit: 800000 });
 | 
			
		||||
    const daiBalance = await daiContract.methods.balanceOf(contract.address).call();
 | 
			
		||||
    expect(+daiBalance).to.be.at.least(+ether('100'))
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
	it('should transfer DAI to CurveProtocol', async () => {
 | 
			
		||||
		let account = accounts[0]
 | 
			
		||||
		let contract = await CurveProtocol.deployed()
 | 
			
		||||
		// Get 100 DAI for first 5 accounts
 | 
			
		||||
		// daiAddress is passed to ganache-cli with flag `--unlock`
 | 
			
		||||
		// so we can use the `transfer` method
 | 
			
		||||
		await daiContract.methods
 | 
			
		||||
			.transfer(contract.address, ether('100').toString())
 | 
			
		||||
			.send({ from: userAddress, gasLimit: 800000 });
 | 
			
		||||
		const daiBalance = await daiContract.methods.balanceOf(contract.address).call();
 | 
			
		||||
		expect(+daiBalance).to.be.at.least(+ether('100'))	
 | 
			
		||||
	});
 | 
			
		||||
  it('should approve DAI to CurveProtocol', async() => {
 | 
			
		||||
    let account = accounts[0]
 | 
			
		||||
    let contract = await CurveProtocol.deployed()
 | 
			
		||||
 | 
			
		||||
	it('should approve DAI to CurveProtocol', async() => {
 | 
			
		||||
		let account = accounts[0]
 | 
			
		||||
		let contract = await CurveProtocol.deployed()
 | 
			
		||||
    await daiContract.methods
 | 
			
		||||
          .approve(contract.address, ether('100').toString())
 | 
			
		||||
          .send({ from: account, gasLimit: 800000 });
 | 
			
		||||
      const daiAllowance = await daiContract.methods.allowance(account, contract.address).call()
 | 
			
		||||
      expect(+daiAllowance).to.be.at.least(+ether('100'))
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
		await daiContract.methods
 | 
			
		||||
	        .approve(contract.address, ether('100').toString())
 | 
			
		||||
	        .send({ from: account, gasLimit: 800000 });
 | 
			
		||||
	    const daiAllowance = await daiContract.methods.allowance(account, contract.address).call()
 | 
			
		||||
	    expect(+daiAllowance).to.be.at.least(+ether('100'))
 | 
			
		||||
	});
 | 
			
		||||
  /* Deprecated as CurveProtocol is not ICurve and exchange has been implemented into sell method
 | 
			
		||||
  it('should exchange', async () => {
 | 
			
		||||
    let account = accounts[0]
 | 
			
		||||
    let contract = await CurveProtocol.deployed()
 | 
			
		||||
 | 
			
		||||
	it('should exchange', async () => {
 | 
			
		||||
		let account = accounts[0]
 | 
			
		||||
		let contract = await CurveProtocol.deployed()
 | 
			
		||||
    // Get 100 DAI for first 5 accounts
 | 
			
		||||
    console.log('before');
 | 
			
		||||
    let get_dy = await contract.get_dy.call(0, 1, ether('1').toString())
 | 
			
		||||
    console.log('after');
 | 
			
		||||
    let min_dy = +get_dy * 0.99
 | 
			
		||||
    let receipt = await contract.exchange(0, 1, ether('1').toString(), 1, { from: account })
 | 
			
		||||
    let buyAmount = receipt.logs[0].args.buyAmount.toString()
 | 
			
		||||
    expect(+buyAmount).to.be.at.least(min_dy);
 | 
			
		||||
  });
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
		// Get 100 DAI for first 5 accounts
 | 
			
		||||
		let get_dy = await contract.get_dy.call(0, 1, ether('1').toString())
 | 
			
		||||
		let min_dy = +get_dy * 0.99
 | 
			
		||||
		let receipt = await contract.exchange(0, 1, ether('1').toString(), 1, { from: account })
 | 
			
		||||
		let buyAmount = receipt.logs[0].args.buyAmount.toString()
 | 
			
		||||
		expect(+buyAmount).to.be.at.least(min_dy);	
 | 
			
		||||
  /* Deprecated as CurveProtocol is not ICurve and calc_token_amount has been implemented into withdraw method
 | 
			
		||||
  it('should add liquidity', async () => {
 | 
			
		||||
    let account = accounts[0]
 | 
			
		||||
    let contract = await CurveProtocol.deployed()
 | 
			
		||||
 | 
			
		||||
	});
 | 
			
		||||
    let amounts = [ether('1').toString(), 0, 0, 0]
 | 
			
		||||
    let token_amount = await contract.calc_token_amount.call(amounts, true)
 | 
			
		||||
 | 
			
		||||
	it('should add liquidity', async () => {
 | 
			
		||||
		let account = accounts[0]
 | 
			
		||||
		let contract = await CurveProtocol.deployed()
 | 
			
		||||
    let receipt = await contract.add_liquidity(amounts, 1, { from: account })
 | 
			
		||||
    let mintAmount = receipt.logs[0].args.mintAmount.toString()
 | 
			
		||||
    expect(+mintAmount).to.be.at.least(+mintAmount)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
		let amounts = [ether('1').toString(), 0, 0, 0]
 | 
			
		||||
		let token_amount = await contract.calc_token_amount.call(amounts, true)
 | 
			
		||||
  it('should remove liquidity imbalance', async () => {
 | 
			
		||||
    let account = accounts[0]
 | 
			
		||||
    let contract = await CurveProtocol.deployed()
 | 
			
		||||
 | 
			
		||||
		let receipt = await contract.add_liquidity(amounts, 1, { from: account })
 | 
			
		||||
		let mintAmount = receipt.logs[0].args.mintAmount.toString()
 | 
			
		||||
		expect(+mintAmount).to.be.at.least(+mintAmount)
 | 
			
		||||
	})
 | 
			
		||||
    let tokenBalance = await tokenContract.methods.balanceOf(contract.address).call()
 | 
			
		||||
    let receipt = await contract.remove_liquidity_imbalance(["100000000000", 0, 0, 0], { from: account })
 | 
			
		||||
    let burnAmount = receipt.logs[0].args.burnAmount.toString()
 | 
			
		||||
    let tokenBalanceAfter = await tokenContract.methods.balanceOf(contract.address).call()
 | 
			
		||||
 | 
			
		||||
	it('should remove liquidity imbalance', async () => {
 | 
			
		||||
		let account = accounts[0]
 | 
			
		||||
		let contract = await CurveProtocol.deployed()
 | 
			
		||||
    //weird Ganache errors sometimes "cannot decode event"
 | 
			
		||||
    console.log(+tokenBalance, +tokenBalanceAfter, +burnAmount)
 | 
			
		||||
    //expect(BN(tokenBalance)).to.be.a.bignumber.equal(BN(tokenBalanceAfter).add(burnAmount))
 | 
			
		||||
 | 
			
		||||
		let tokenBalance = await tokenContract.methods.balanceOf(contract.address).call()
 | 
			
		||||
		let receipt = await contract.remove_liquidity_imbalance(["100000000000", 0, 0, 0], { from: account })
 | 
			
		||||
		let burnAmount = receipt.logs[0].args.burnAmount.toString()
 | 
			
		||||
		let tokenBalanceAfter = await tokenContract.methods.balanceOf(contract.address).call()
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
		//weird Ganache errors sometimes "cannot decode event"
 | 
			
		||||
		console.log(+tokenBalance, +tokenBalanceAfter, +burnAmount)
 | 
			
		||||
		//expect(BN(tokenBalance)).to.be.a.bignumber.equal(BN(tokenBalanceAfter).add(burnAmount))
 | 
			
		||||
  it('should remove liquidity in one coin', async() => {
 | 
			
		||||
    let account = accounts[0]
 | 
			
		||||
    let contract = await CurveProtocol.deployed()
 | 
			
		||||
 | 
			
		||||
	})
 | 
			
		||||
    let daiBalance = await daiContract.methods.balanceOf(contract.address).call()
 | 
			
		||||
    let receipt = await contract.remove_liquidity_one_coin("100000000000", 0, 1, { from: account })
 | 
			
		||||
    let withdrawnAmount = receipt.logs[0].args.withdrawnAmount.toString()
 | 
			
		||||
    let daiBalanceAfter = await daiContract.methods.balanceOf(contract.address).call()
 | 
			
		||||
 | 
			
		||||
	it('should remove liquidity in one coin', async() => {
 | 
			
		||||
		let account = accounts[0]
 | 
			
		||||
		let contract = await CurveProtocol.deployed()
 | 
			
		||||
 | 
			
		||||
		let daiBalance = await daiContract.methods.balanceOf(contract.address).call()
 | 
			
		||||
		let receipt = await contract.remove_liquidity_one_coin("100000000000", 0, 1, { from: account })
 | 
			
		||||
		let withdrawnAmount = receipt.logs[0].args.withdrawnAmount.toString()
 | 
			
		||||
		let daiBalanceAfter = await daiContract.methods.balanceOf(contract.address).call()
 | 
			
		||||
 | 
			
		||||
		//weird Ganache errors sometimes "cannot decode event"
 | 
			
		||||
		console.log(+daiBalance, +daiBalanceAfter, +withdrawnAmount)
 | 
			
		||||
		//expect(BN(daiBalance)).to.be.a.bignumber.equal(BN(daiBalanceAfter).sub(withdrawnAmount));
 | 
			
		||||
	})
 | 
			
		||||
});
 | 
			
		||||
    //weird Ganache errors sometimes "cannot decode event"
 | 
			
		||||
    console.log(+daiBalance, +daiBalanceAfter, +withdrawnAmount)
 | 
			
		||||
    //expect(BN(daiBalance)).to.be.a.bignumber.equal(BN(daiBalanceAfter).sub(withdrawnAmount));
 | 
			
		||||
  })
 | 
			
		||||
  */
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,6 +54,12 @@ module.exports = {
 | 
			
		|||
     port: 8545,            // Standard Ethereum port (default: none)
 | 
			
		||||
     network_id: "*",       // Any network (default: none)
 | 
			
		||||
    },
 | 
			
		||||
    // Tenderly Proxy
 | 
			
		||||
    proxy: {
 | 
			
		||||
     host: "127.0.0.1",     // Localhost (default: none)
 | 
			
		||||
     port: 9545,            // Standard Ethereum port (default: none)
 | 
			
		||||
     network_id: "*",       // Any network (default: none)
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Another network with more advanced options...
 | 
			
		||||
    // advanced: {
 | 
			
		||||
| 
						 | 
				
			
			@ -108,7 +114,7 @@ module.exports = {
 | 
			
		|||
  // Configure your compilers
 | 
			
		||||
  compilers: {
 | 
			
		||||
    solc: {
 | 
			
		||||
      version: "v0.6.0",    // Fetch exact version from solc-bin (default: truffle's version)
 | 
			
		||||
      version: "v0.6.2",    // Fetch exact version from solc-bin (default: truffle's version)
 | 
			
		||||
      // docker: true,        // Use "0.5.1" you've installed locally with docker (default: false)
 | 
			
		||||
      // settings: {          // See the solidity docs for advice about optimization and evmVersion
 | 
			
		||||
      //  optimizer: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user