contract ProxyCurve is Operator {
    using SafeERC20 for IERC20;
    using SafeMath for uint256;

    address public pool; //Address of the Curve metapool
    address public cash; //Address of the Curve metapool
    address public feeChecker; //Checks whether a transaction is taxed and returns the tax amount
    address public feeDistributor; //Handles distributing the tax

    constructor(address _pool, address _cash) public {
        pool = _pool;
        cash = _cash;
    }

    
    /// @notice Perform an exchange from MIC to one of the 3CRV tokens (frontend should only use this contract when selling MIC, otherwise use the metapool contract itself)
    /// @dev Index values can be found via the `underlying_coins` public getter method
    /// @param j Index value of the underlying coin to recieve
    /// @param dx Amount of MIC being exchanged
    /// @param min_dy Minimum amount of `j` to receive, should be calculated on the website based on `transferToAmount` (the amount remaining after the tax)
    /// @return Actual amount of `j` received
    function exchangeMIC(int128 j, uint256 dx, uint256 min_dy) external returns (uint256) {
        //Transfer tokens from the caller
        IERC20(cash).safeTransferFrom(msg.sender, address(this), dx);

        if(IFeeChecker(feeChecker).isTransferTaxed2()) {
            //Calculate tax
            uint256 feeAmount = IFeeChecker(feeChecker).calculateFeeAmount(address(this), pool, dx);
            uint256 transferToAmount = dx.sub(feeAmount);

            //Send to fee distributor
            IERC20(cash).safeTransfer(feeDistributor, feeAmount);
            IFeeDistributor(feeDistributor).addFee(feeAmount);

            //Approve Curve metapool and exchange the amount remaining after the tax
            IERC20(cash).safeApprove(pool, 0);
            IERC20(cash).safeApprove(pool, transferToAmount);

            //For metapools: 0 = the token (i.e. Frax, MIC, etc), 1 = DAI, 2 = USDC, 3 = USDT
            //_receiver = msg.sender, so tokens are sent to the user 
            ICurveMeta2(pool).exchange_underlying(0, j, transferToAmount, min_dy, msg.sender);
        }
        else {
            //Transaction isn't taxed, so just do a normal swap
            //To save gas, the website should use the metapool contract when transactions aren't taxed
            IERC20(cash).safeApprove(pool, 0);
            IERC20(cash).safeApprove(pool, dx);
            ICurveMeta2(pool).exchange_underlying(0, j, dx, min_dy, msg.sender);
        }
    }

    function setFeeCheckerAddress(address _address) public onlyOperator {
        feeChecker = _address;
    }

    function setFeeDistributorAddress(address _address) public onlyOperator {
        feeDistributor = _address;
    }
}
function exchangeMIC(int128 j, uint256 dx, uint256 min_dy) external returns (uint256) {
    //Transfer tokens from the caller
    IERC20(cash).safeTransferFrom(msg.sender, address(this), dx);

    if(IFeeChecker(feeChecker).isTransferTaxed2()) {
        //Calculate tax
        uint256 feeAmount = IFeeChecker(feeChecker).calculateFeeAmount(address(this), pool, dx);
        uint256 transferToAmount = dx.sub(feeAmount);

        //Send to fee distributor
        IERC20(cash).safeTransfer(feeDistributor, feeAmount);
        IFeeDistributor(feeDistributor).addFee(feeAmount);

        //Approve Curve metapool and exchange the amount remaining after the tax
        IERC20(cash).safeApprove(pool, 0);
        IERC20(cash).safeApprove(pool, transferToAmount);

        //For metapools: 0 = the token (i.e. Frax, MIC, etc), 1 = DAI, 2 = USDC, 3 = USDT
        //_receiver = msg.sender, so tokens are sent to the user 
        ICurveMeta2(pool).exchange_underlying(0, j, transferToAmount, min_dy, msg.sender);
    }
    else {
        //Transaction isn't taxed, so just do a normal swap
        //To save gas, the website should use the metapool contract when transactions aren't taxed
        IERC20(cash).safeApprove(pool, 0);
        IERC20(cash).safeApprove(pool, dx);
        ICurveMeta2(pool).exchange_underlying(0, j, dx, min_dy, msg.sender);
    }
}

/// @notice Perform an exchange from MIC to one of the 3CRV tokens (frontend should only use this contract when selling MIC, otherwise use the metapool contract itself)
/// @dev Index values can be found via the `underlying_coins` public getter method
/// @param j Index value of the underlying coin to recieve
/// @param dx Amount of MIC being exchanged
/// @param min_dy Minimum amount of `j` to receive, should be calculated on the website based on `transferToAmount` (the amount remaining after the tax)
/// @return Actual amount of `j` received