EthereumEthereum
0xf2...d154
FirstDerivative

FirstDerivative

FDV

代币
市值
$1.00
 
价格
2%
此合同的源代码已经过验证!
合同元数据
编译器
0.6.12+commit.27d51765
语言
Solidity
合同源代码
文件 1 的 1:Untitled.sol
abstract contract TokenManager {
    
    address constant COMPOUND_DEPOSIT_ADDRESS = 0xeB21209ae4C2c9FF2a86ACA31E123764A3B6Bc06;
    address constant Y_DEPOSIT_ADDRESS      = 0xbBC81d23Ea2c3ec7e56D39296F0cbB648873a5d3;
    address constant BUSD_DEPOSIT_ADDRESS   = 0xb6c057591E073249F2D9D88Ba59a46CFC9B59EdB;
    address constant PAX_DEPOSIT_ADDRESS    = 0xA50cCc70b6a011CffDdf45057E39679379187287;
    address constant REN_DEPOSIT_ADDRESS    = 0x93054188d876f558f4a66B2EF1d97d16eDf0895B;
    address constant SBTC_DEPOSIT_ADDRESS   = 0x7fC77b5c7614E1533320Ea6DDc2Eb61fa00A9714;
    address constant HBTC_DEPOSIT_ADDRESS   = 0x4CA9b3063Ec5866A4B82E437059D2C43d1be596F;
    
    address constant SWERVE_DEPOSIT_ADDRESS     = 0x329239599afB305DA0A2eC69c58F8a6697F9F88d;


    address constant COMPOUND_TOKEN_ADDRESS     = 0x845838DF265Dcd2c412A1Dc9e959c7d08537f8a2;
    address constant Y_TOKEN_ADDRESS        = 0xdF5e0e81Dff6FAF3A7e52BA697820c5e32D806A8;
    address constant BUSD_TOKEN_ADDRESS         = 0x3B3Ac5386837Dc563660FB6a0937DFAa5924333B;
    address constant PAX_TOKEN_ADDRESS      = 0xD905e2eaeBe188fc92179b6350807D8bd91Db0D8;
    address constant REN_TOKEN_ADDRESS      = 0x49849C98ae39Fff122806C06791Fa73784FB3675;
    address constant SBTC_TOKEN_ADDRESS         = 0x075b1bb99792c9E1041bA13afEf80C91a1e70fB3;
    address constant HBTC_TOKEN_ADDRESS         = 0xb19059ebb43466C323583928285a49f558E572Fd;
    address constant SRW_TOKEN_ADDRESS      = 0x77C6E4a580c0dCE4E5c7a17d0bc077188a83A059;
    

    address constant COMPOUND_GAUGE_ADDRESS     = 0x7ca5b0a2910B33e9759DC7dDB0413949071D7575;
    address constant Y_GAUGE_ADDRESS        = 0xFA712EE4788C042e2B7BB55E6cb8ec569C4530c1;
    address constant BUSD_GAUGE_ADDRESS         = 0x69Fb7c45726cfE2baDeE8317005d3F94bE838840;
    address constant PAX_GAUGE_ADDRESS      = 0x64E3C23bfc40722d3B649844055F1D51c1ac041d;
    address constant REN_GAUGE_ADDRESS      = 0xB1F2cdeC61db658F091671F5f199635aEF202CAC;
    address constant SBTC_GAUGE_ADDRESS         = 0x705350c4BcD35c9441419DdD5d2f097d7a55410F;
    address constant SWERVE_GAUGE_ADDRESS   = 0xb4d0C929cD3A1FbDc6d57E7D3315cF0C4d6B4bFa;
    address constant HBTC_GAUGE_ADDRESS         = 0x4c18E409Dc8619bFb6a1cB56D114C3f592E0aE79;

    address constant CRV_TOKEN_MINTER_ADDRESS   = 0xd061D61a4d941c39E5453435B6345Dc261C2fcE0;
    address constant SWERVE_TOKEN_MINTER_ADDRESS = 0x2c988c3974AD7E604E276AE0294a7228DEf67974;
    
    address constant CRV_TOKEN_ADDRESS      = 0xD533a949740bb3306d119CC777fa900bA034cd52;
    address constant SWERVE_TOKEN_ADDRESS   = 0xB8BAa0e4287890a5F79863aB62b7F175ceCbD433;
    

    address constant VOTING_ESCROW          = 0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2;
    
    address constant EXCHANGE_CONTRACT  = 0xC586BeF4a0992C495Cf22e1aeEE4E446CECDee0E;
    address constant ETH_ADDRESS        = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
    address constant DAI_ADDRESS        = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
    address constant WBTC_ADDRESS        = 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599;
    
    address constant USDC_ADDRESS        = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
    address constant USDT_ADDRESS        = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
    address constant TUSD_ADDRESS        = 0x0000000000085d4780B73119b644AE5ecd22b376;
    
    mapping(address => address[]) public supportAddresses;
    
    function getSupportAddresses(address _depositAddress) public view returns(address[] memory){
        return supportAddresses[_depositAddress];
    }
    
    
    constructor() public {
        
        supportAddresses[COMPOUND_DEPOSIT_ADDRESS].push(COMPOUND_TOKEN_ADDRESS);
        supportAddresses[COMPOUND_DEPOSIT_ADDRESS].push(COMPOUND_GAUGE_ADDRESS);
        
        supportAddresses[Y_DEPOSIT_ADDRESS].push(Y_TOKEN_ADDRESS);
        supportAddresses[Y_DEPOSIT_ADDRESS].push(Y_GAUGE_ADDRESS);
        
        supportAddresses[BUSD_DEPOSIT_ADDRESS].push(BUSD_TOKEN_ADDRESS);
        supportAddresses[BUSD_DEPOSIT_ADDRESS].push(BUSD_GAUGE_ADDRESS);
        
        supportAddresses[PAX_DEPOSIT_ADDRESS].push(PAX_TOKEN_ADDRESS);
        supportAddresses[PAX_DEPOSIT_ADDRESS].push(PAX_GAUGE_ADDRESS);
        
        supportAddresses[REN_DEPOSIT_ADDRESS].push(REN_TOKEN_ADDRESS);
        supportAddresses[REN_DEPOSIT_ADDRESS].push(REN_GAUGE_ADDRESS);
        
        supportAddresses[SBTC_DEPOSIT_ADDRESS].push(SBTC_TOKEN_ADDRESS);
        supportAddresses[SBTC_DEPOSIT_ADDRESS].push(SBTC_GAUGE_ADDRESS);
        
        supportAddresses[HBTC_DEPOSIT_ADDRESS].push(HBTC_TOKEN_ADDRESS);
        supportAddresses[HBTC_DEPOSIT_ADDRESS].push(HBTC_GAUGE_ADDRESS);
        
        supportAddresses[SWERVE_DEPOSIT_ADDRESS].push(SRW_TOKEN_ADDRESS);
        supportAddresses[SWERVE_DEPOSIT_ADDRESS].push(SWERVE_GAUGE_ADDRESS);
        
    }
}

pragma solidity ^0.6.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies in extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        return _functionCallWithValue(target, data, value, errorMessage);
    }

    function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20 {
    using SafeMath for uint256;
    using Address for address;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;
    uint8 private _decimals;

    /**
     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
     * a default value of 18.
     *
     * To select a different value for {decimals}, use {_setupDecimals}.
     *
     * All three of these values are immutable: they can only be set once during
     * construction.
     */
    constructor (string memory name, string memory symbol) public {
        _name = name;
        _symbol = symbol;
        _decimals = 18;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
     * called.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view returns (uint8) {
        return _decimals;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20};
     *
     * Requirements:
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Sets {decimals} to a value other than the default one of 18.
     *
     * WARNING: This function should only be called from the constructor. Most
     * applications that interact with token contracts will not expect
     * {decimals} to ever change, and may work incorrectly if it does.
     */
    function _setupDecimals(uint8 decimals_) internal {
        _decimals = decimals_;
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}

contract FirstDerivative is ERC20 {
    constructor() public ERC20("FirstDerivative", "FDV") {
        _mint(msg.sender, 60000*10**18);
    }
}

// abstract contract IOneSplitView {
//     // disableFlags = FLAG_DISABLE_UNISWAP + FLAG_DISABLE_KYBER + ...
//     uint256 public constant FLAG_DISABLE_UNISWAP = 0x01;
//     uint256 public constant FLAG_DISABLE_KYBER = 0x02;
//     uint256 public constant FLAG_ENABLE_KYBER_UNISWAP_RESERVE = 0x100000000; // Turned off by default
//     uint256 public constant FLAG_ENABLE_KYBER_OASIS_RESERVE = 0x200000000; // Turned off by default
//     uint256 public constant FLAG_ENABLE_KYBER_BANCOR_RESERVE = 0x400000000; // Turned off by default
//     uint256 public constant FLAG_DISABLE_BANCOR = 0x04;
//     uint256 public constant FLAG_DISABLE_OASIS = 0x08;
//     uint256 public constant FLAG_DISABLE_COMPOUND = 0x10;
//     uint256 public constant FLAG_DISABLE_FULCRUM = 0x20;
//     uint256 public constant FLAG_DISABLE_CHAI = 0x40;
//     uint256 public constant FLAG_DISABLE_AAVE = 0x80;
//     uint256 public constant FLAG_DISABLE_SMART_TOKEN = 0x100;
//     uint256 public constant FLAG_ENABLE_MULTI_PATH_ETH = 0x200; // Turned off by default
//     uint256 public constant FLAG_DISABLE_BDAI = 0x400;
//     uint256 public constant FLAG_DISABLE_IEARN = 0x800;
//     uint256 public constant FLAG_DISABLE_CURVE_COMPOUND = 0x1000;
//     uint256 public constant FLAG_DISABLE_CURVE_USDT = 0x2000;
//     uint256 public constant FLAG_DISABLE_CURVE_Y = 0x4000;
//     uint256 public constant FLAG_DISABLE_CURVE_BINANCE = 0x8000;
//     uint256 public constant FLAG_ENABLE_MULTI_PATH_DAI = 0x10000; // Turned off by default
//     uint256 public constant FLAG_ENABLE_MULTI_PATH_USDC = 0x20000; // Turned off by default
//     uint256 public constant FLAG_DISABLE_CURVE_SYNTHETIX = 0x40000;
//     uint256 public constant FLAG_DISABLE_WETH = 0x80000;
//     uint256 public constant FLAG_ENABLE_UNISWAP_COMPOUND = 0x100000; // Works only with FLAG_ENABLE_MULTI_PATH_ETH

//     function getExpectedReturn(
//         IERC20 fromToken,
//         IERC20 toToken,
//         uint256 amount,
//         uint256 parts,
//         uint256 disableFlags
//     )
//         virtual
//         public
//         view
//         returns(
//             uint256 returnAmount,
//             uint256[] memory distribution
//         );
// }


// abstract contract IOneSplit is IOneSplitView {
//     function swap(
//         IERC20 fromToken,
//         IERC20 toToken,
//         uint256 amount,
//         uint256 minReturn,
//         uint256[] memory distribution,
//         uint256 disableFlags
//     ) virtual public payable;
// }

// contract PoolFactoryProxy is TokenManager {
//     address public owner;
//     address public implementation;
    
//     address public poolTokenAddress;
//     address public poolTokenBTCAddress;
//     address public poolProxy;
    
//     mapping (address => address) public usersStablePools;
//     mapping (address => address) public usersBTCPools;
//     uint public totalBalance;
    
//     mapping(bool => address) public bestBoost;
    
    
//     constructor(address _poolProxyAddress, address _poolTokenAddress, address _poolTokenBTCAddress, address _impl) public {
//         implementation = _impl;
//         poolProxy = _poolProxyAddress;
//         poolTokenAddress = _poolTokenAddress;
//         poolTokenBTCAddress = _poolTokenBTCAddress;
//         owner = msg.sender;
//     }

//     function setImplementation(address _newImpl) public {
//         require(msg.sender == owner);

//         implementation = _newImpl;
//     }
   
//     fallback() virtual external {
//         address impl = implementation;
//         assembly {
//             let ptr := mload(0x40)
 
//             // (1) copy incoming call data
//             calldatacopy(ptr, 0, calldatasize())
 
//              // (2) forward call to logic contract
//             let result := delegatecall(gas(), impl, ptr, calldatasize(), 0, 0)
//             let size := returndatasize()
 
//             // (3) retrieve return data
//             returndatacopy(ptr, 0, size)
 
//             // (4) forward return data back to caller
//             switch result
//             case 0 { revert(ptr, size) }
//             default { return(ptr, size) }
//         }   
//     }
// }

// contract PoolFactory is TokenManager {
//     address public owner;

//     address public poolTokenAddress;
//     address public poolTokenBTCAddress;
//     address public poolProxy;
    
//     mapping (address => address) public usersStablePools;
//     mapping (address => address) public usersBTCPools;
//     uint public totalBalance;
    
//     mapping(bool => address) public bestBoost;
    
//     event NewPool(address indexed poolAddress, address indexed sender, bool isBTC);

//     modifier poolOnly(address userAddress) {
//         require(msg.sender == usersStablePools[userAddress] || msg.sender == usersBTCPools[userAddress]);
//         _;
//     }
    
    
//     function setPoolProxyAddress(address _newProxy) public {
//         require(msg.sender == owner);
//         poolProxy = _newProxy;
//     }
    
//     function newStablePool() public {
//         require(usersStablePools[msg.sender] == address(0), "pool already created");
//         PoolProxy pool = new PoolProxy(msg.sender, false);
//         usersStablePools[msg.sender] = address(pool);
        
//         emit NewPool(address(pool), msg.sender, false);
//     }
    
//     function newBTCPool() public {
//         require(usersBTCPools[msg.sender] == address(0), "pool already created");
//         PoolProxy pool = new PoolProxy(msg.sender, true);
//         usersBTCPools[msg.sender] = address(pool);
        
//         emit NewPool(address(pool), msg.sender, true);
//     }

//     function setBestBoost(address _newBestBoost, address _newBestBoostBTC) public {
//         require(msg.sender == owner);
//         bestBoost[false] = _newBestBoost;
//         bestBoost[true] = _newBestBoostBTC;
//     }
    
//     function mint(address to, uint amount, bool isBTCPool) public poolOnly(to) {
//         if(isBTCPool) {
//             PoolToken(poolTokenBTCAddress).mint(to, amount);
//         } else {
//             PoolToken(poolTokenAddress).mint(to, amount);
//         }
        
//     }
    
//     function burn(address from, uint amount, bool isBTCPool) public poolOnly(from) {
//         if(isBTCPool) {
//             PoolToken(poolTokenBTCAddress).burn(from, amount);
//         } else {
//             PoolToken(poolTokenAddress).burn(from, amount);
//         }
//     }
// }

// contract Deposit2Tokens {
//     function add_liquidity(uint256[2] memory uamounts, uint256 min_mint_amount) public{}
    
//     function remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 min_uamount, bool donate_dust) public{}
//     uint[100000000000000000000000000000] public period_timestamp;
// }

// contract Deposit3Tokens {
//     function add_liquidity(uint256[3] memory uamounts, uint256 min_mint_amount) public{}
//     function remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 min_uamount) public{}
//     uint[100000000000000000000000000000] public period_timestamp;
// }

// abstract contract Deposit4Tokens {
//     function add_liquidity(uint[4] memory uamounts, uint256 min_mint_amount) virtual public;
//     function remove_liquidity(uint256 _amount, uint256[4] memory min_amounts) public{}
//     function remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 min_uamount, bool donate_dust) virtual public;
//     uint[100000000000000000000000000000] public period_timestamp;
// }

// abstract contract IGauge {
//   function deposit(uint256 _value) virtual public;
//   function withdraw(uint256 _value) virtual public;

//   mapping(address => uint) public balanceOf;
// }


// abstract contract TokenMinter {
//     function mint(address gauge_addr) virtual public;
// }

// contract PoolProxy is TokenManager {
    
//     address public owner;
//     address public poolFactoryAddress;
//     bool public isBTCPool;

//     constructor(address _owner, bool _isBTCPool) public {
//         poolFactoryAddress = msg.sender;
//         owner = _owner;
//         isBTCPool = _isBTCPool;
//     }

//     fallback() external payable {
//         address impl = implementation();
//         assembly {
//             let ptr := mload(0x40)
 
//             // (1) copy incoming call data
//             calldatacopy(ptr, 0, calldatasize())
 
//              // (2) forward call to logic contract
//             let result := delegatecall(gas(), impl, ptr, calldatasize(), 0, 0)
//             let size := returndatasize()
 
//             // (3) retrieve return data
//             returndatacopy(ptr, 0, size)
 
//             // (4) forward return data back to caller
//             switch result
//             case 0 { revert(ptr, size) }
//             default { return(ptr, size) }
//         }   
//     }

//     function implementation() public view returns(address) {
//         return PoolFactory(poolFactoryAddress).poolProxy();
//     }
// }

// contract Pool is TokenManager {
    
//     address public owner;
//     address public poolFactoryAddress;
//     bool public isBTCPool;
    
//     modifier onlyOwner() {
//         require (msg.sender == owner); 
//         _; 
//     }

//     function deposit(address tokenAddress, uint amount) public payable {
        
//         address poolAddress = PoolFactory(poolFactoryAddress).bestBoost(isBTCPool);
       
//         if (isBTCPool) {
//             _btcDeposit(poolAddress, tokenAddress, amount);
//             return;
//         }
        
        
//         if (msg.value > 0) {
//             _ethDeposit(poolAddress);
//             return;
//         }
        
//         uint _amount = amount;
//         uint[] memory _distribution;

//         IERC20(tokenAddress).transferFrom(msg.sender, address(this), amount);

//         if (tokenAddress != DAI_ADDRESS) {
//             IERC20(tokenAddress).approve(EXCHANGE_CONTRACT, amount);
//             (_amount, _distribution) = IOneSplit(EXCHANGE_CONTRACT).getExpectedReturn(IERC20(tokenAddress), IERC20(DAI_ADDRESS), amount, 100, 0);
//             IOneSplit(EXCHANGE_CONTRACT).swap(IERC20(tokenAddress), IERC20(DAI_ADDRESS), amount, _amount, _distribution, 0);
//         }

        
//         (address lpTokenAddress, address gaugeAddress) = _deposit(poolAddress, _amount);
        
//         PoolFactory(poolFactoryAddress).mint(msg.sender, IERC20(lpTokenAddress).balanceOf(address(this)), isBTCPool);

//         depositLPTokens(lpTokenAddress, gaugeAddress, IERC20(lpTokenAddress).balanceOf(address(this)));
        
        
//     }
    
//     function _btcDeposit(address poolAddress, address tokenAddress, uint amount) internal {
//         uint _amount;
//         uint[] memory _distribution;
            
//         if (msg.value > 0) {
//             (_amount, _distribution) = IOneSplit(EXCHANGE_CONTRACT).getExpectedReturn(IERC20(ETH_ADDRESS), IERC20(WBTC_ADDRESS), msg.value, 100, 0);
//             IOneSplit(EXCHANGE_CONTRACT).swap.value(msg.value)(IERC20(ETH_ADDRESS), IERC20(WBTC_ADDRESS), msg.value, _amount, _distribution, 0);

//             uint wBTCamount = IERC20(WBTC_ADDRESS).balanceOf(address(this));
            
//             (address lpTokenAddress, address gaugeAddress) = _deposit(poolAddress, _amount);
            
//             uint lpAmount = IERC20(lpTokenAddress).balanceOf(address(this));
            
            
//             PoolFactory(poolFactoryAddress).mint(msg.sender, IERC20(lpTokenAddress).balanceOf(address(this)), isBTCPool);
//             depositLPTokens(lpTokenAddress, gaugeAddress, IERC20(lpTokenAddress).balanceOf(address(this)));
//         }
        
//         IERC20(tokenAddress).transferFrom(msg.sender, address(this), amount);

//         if (tokenAddress != WBTC_ADDRESS) {
//             IERC20(tokenAddress).approve(EXCHANGE_CONTRACT, amount);
//             (_amount, _distribution) = IOneSplit(EXCHANGE_CONTRACT).getExpectedReturn(IERC20(tokenAddress), IERC20(WBTC_ADDRESS), amount, 100, 0);
//             IOneSplit(EXCHANGE_CONTRACT).swap(IERC20(tokenAddress), IERC20(WBTC_ADDRESS), amount, _amount, _distribution, 0);
//         }

//         (address lpTokenAddress, address gaugeAddress) = _deposit(poolAddress, _amount);
        
        
//         PoolFactory(poolFactoryAddress).mint(msg.sender, IERC20(lpTokenAddress).balanceOf(address(this)), isBTCPool);
//         depositLPTokens(lpTokenAddress, gaugeAddress, IERC20(lpTokenAddress).balanceOf(address(this)));
//     }

//     function claimReward(address _depositAddress, bool isHarvest) public onlyOwner {
        
//         address[] memory supAddresses = getSupportAddresses(_depositAddress); 
//         if (supAddresses[1] == SWERVE_GAUGE_ADDRESS) {
//             TokenMinter(SWERVE_TOKEN_MINTER_ADDRESS).mint(supAddresses[1]);
//         } else {
//             TokenMinter(CRV_TOKEN_MINTER_ADDRESS).mint(supAddresses[1]);
//         }
        
        
//         uint swerveTokenBalance = IERC20(SWERVE_TOKEN_ADDRESS).balanceOf(address(this));
//         uint crvTokenBalance = IERC20(CRV_TOKEN_ADDRESS).balanceOf(address(this));
        
//         if (isHarvest) {
//             uint _amount;
//             uint[] memory _distribution;
            
//             if (swerveTokenBalance > 0) {
//                 IERC20(SWERVE_TOKEN_ADDRESS).approve(EXCHANGE_CONTRACT, swerveTokenBalance);
//                 (_amount, _distribution) = IOneSplit(EXCHANGE_CONTRACT).getExpectedReturn(IERC20(SWERVE_TOKEN_ADDRESS), IERC20(DAI_ADDRESS), swerveTokenBalance, 100, 0);
//                 IOneSplit(EXCHANGE_CONTRACT).swap(IERC20(SWERVE_TOKEN_ADDRESS), IERC20(DAI_ADDRESS), swerveTokenBalance, _amount, _distribution, 0);
//             }
            
//             if (crvTokenBalance > 0) {
//                 IERC20(CRV_TOKEN_ADDRESS).approve(EXCHANGE_CONTRACT, crvTokenBalance);
//                 (_amount, _distribution) = IOneSplit(EXCHANGE_CONTRACT).getExpectedReturn(IERC20(CRV_TOKEN_ADDRESS), IERC20(DAI_ADDRESS), crvTokenBalance, 100, 0);
//                 IOneSplit(EXCHANGE_CONTRACT).swap(IERC20(CRV_TOKEN_ADDRESS), IERC20(DAI_ADDRESS), crvTokenBalance, _amount, _distribution, 0);
//             }
            
//             uint daiBalance = IERC20(DAI_ADDRESS).balanceOf(address(this));
            
//             if(daiBalance > 0) {
//                 IERC20(DAI_ADDRESS).transfer(msg.sender, daiBalance);
//             }
            
//             return;
//         }
        
        
//         if(swerveTokenBalance > 0) {
//             IERC20(SWERVE_TOKEN_ADDRESS).transfer(msg.sender, swerveTokenBalance);
//         }
        
//         if(crvTokenBalance > 0) {
//             IERC20(CRV_TOKEN_ADDRESS).transfer(msg.sender, crvTokenBalance);
//         }
//     }

//     function exit(address _depositAddress, uint value) public onlyOwner {
//         claimReward(_depositAddress, false);
       
            
//         address[] memory supAddresses = getSupportAddresses(_depositAddress);
          
//         require(IGauge(supAddresses[1]).balanceOf(address(this)) > 0);
        
//         IGauge(supAddresses[1]).withdraw(IGauge(supAddresses[1]).balanceOf(address(this)));
        
//         uint bal = IERC20(supAddresses[0]).balanceOf(address(this));
        
//         require(bal > 0);
        
//         PoolFactory(poolFactoryAddress).burn(msg.sender, bal, isBTCPool);
            
//         IERC20(supAddresses[0]).approve(_depositAddress, bal);
//         if (!isBTCPool) {
//           if (_depositAddress == SWERVE_DEPOSIT_ADDRESS) {
//               uint[4] memory buf;
//               Deposit4Tokens(_depositAddress).remove_liquidity(bal, buf);
//           } else {
//                 Deposit2Tokens(_depositAddress).remove_liquidity_one_coin(bal, 0, 1, true);
//           }
//         } else {
//             Deposit3Tokens(_depositAddress).remove_liquidity_one_coin(bal, 1, 1);
           
//         }
        
//         if (!isBTCPool) {
//             if(IERC20(DAI_ADDRESS).balanceOf(address(this)) > 0) {
//                 IERC20(DAI_ADDRESS).transfer(msg.sender, IERC20(DAI_ADDRESS).balanceOf(address(this)));
//             }
            
//             if(IERC20(USDC_ADDRESS).balanceOf(address(this)) > 0) {
//                 IERC20(USDC_ADDRESS).transfer(msg.sender, IERC20(USDC_ADDRESS).balanceOf(address(this)));
//             }
            
//             // if(IERC20(USDT_ADDRESS).balanceOf(address(this)) > 0) {
//             //     IERC20(USDT_ADDRESS).transfer(msg.sender, IERC20(USDT_ADDRESS).balanceOf(address(this)));
//             // }
            
//             if(IERC20(TUSD_ADDRESS).balanceOf(address(this)) > 0) {
//                 IERC20(TUSD_ADDRESS).transfer(msg.sender, IERC20(TUSD_ADDRESS).balanceOf(address(this)));
//             }
//         } else {
//             IERC20(WBTC_ADDRESS).transfer(msg.sender, IERC20(WBTC_ADDRESS).balanceOf(address(this)));
//         }
        
//     }

//     function withdrawTokenFromContract(address tokenAddress, uint amount) public onlyOwner {
//         IERC20(tokenAddress).transfer(msg.sender, amount);
//     }
    
//     function _ethDeposit(address poolAddress) private {
//         uint _amount;
//         uint[] memory _distribution;

//         (_amount, _distribution) = IOneSplit(EXCHANGE_CONTRACT).getExpectedReturn(IERC20(ETH_ADDRESS), IERC20(DAI_ADDRESS), msg.value, 100, 0);
//         IOneSplit(EXCHANGE_CONTRACT).swap.value(msg.value)(IERC20(ETH_ADDRESS), IERC20(DAI_ADDRESS), msg.value, _amount, _distribution, 0);

//         (address lpTokenAddress, address gaugeAddress) = _deposit(poolAddress, _amount);
        
        
//         PoolFactory(poolFactoryAddress).mint(msg.sender, IERC20(lpTokenAddress).balanceOf(address(this)), isBTCPool);
//         depositLPTokens(lpTokenAddress, gaugeAddress, IERC20(lpTokenAddress).balanceOf(address(this)));
//     }
    
//     function depositLPTokens(address lpTokenAddress, address gaugeAddress, uint value) internal {
//         IERC20(lpTokenAddress).approve(gaugeAddress, value);
//         IGauge(gaugeAddress).deposit(value);
//     }

//     function _deposit(address _depositPool, uint amount) internal returns(address, address) {
//         IERC20(DAI_ADDRESS).approve(_depositPool, amount);

//         if(_depositPool == COMPOUND_DEPOSIT_ADDRESS) {
//             uint[2] memory uamounts;
//             uamounts[0] = amount;
//             Deposit2Tokens(_depositPool).add_liquidity(uamounts, 0);
//             return (COMPOUND_TOKEN_ADDRESS, COMPOUND_GAUGE_ADDRESS);
//         }
        
//         if(_depositPool == Y_DEPOSIT_ADDRESS) {
//             uint[4] memory uamounts;
//             uamounts[0] = amount;
//             Deposit4Tokens(_depositPool).add_liquidity(uamounts, 0);
//             return (Y_TOKEN_ADDRESS, Y_GAUGE_ADDRESS);
//         }

//         if(_depositPool == BUSD_DEPOSIT_ADDRESS) {
//             uint[4] memory uamounts;
//             uamounts[0] = amount;
//             Deposit4Tokens(_depositPool).add_liquidity(uamounts, 0);
//             return (BUSD_TOKEN_ADDRESS, BUSD_GAUGE_ADDRESS);
//         }

//         if(_depositPool == PAX_DEPOSIT_ADDRESS) {
//             uint[4] memory uamounts;
//             uamounts[0] = amount;
//             Deposit4Tokens(_depositPool).add_liquidity(uamounts, 0);
//             return (PAX_TOKEN_ADDRESS, PAX_GAUGE_ADDRESS);
//         } 

//         if(_depositPool == REN_DEPOSIT_ADDRESS) {
//             IERC20(WBTC_ADDRESS).approve(_depositPool, amount);
//             uint[2] memory uamounts;
//             uamounts[1] = amount;
//             Deposit2Tokens(_depositPool).add_liquidity(uamounts, 0);
//             return (REN_TOKEN_ADDRESS, REN_GAUGE_ADDRESS);
//         } 

//         if(_depositPool == SBTC_DEPOSIT_ADDRESS) {
//             IERC20(WBTC_ADDRESS).approve(_depositPool, amount);
//             uint[3] memory uamounts;
//             uamounts[1] = amount;
//             Deposit3Tokens(_depositPool).add_liquidity(uamounts, 0);
//             return (SBTC_TOKEN_ADDRESS, SBTC_GAUGE_ADDRESS);
//         }
        
//         if(_depositPool == HBTC_DEPOSIT_ADDRESS) {
//             IERC20(WBTC_ADDRESS).approve(_depositPool, amount);
//             uint[2] memory uamounts;
//             uamounts[1] = amount;
//             Deposit2Tokens(_depositPool).add_liquidity(uamounts, 0);
//             return (HBTC_TOKEN_ADDRESS, HBTC_GAUGE_ADDRESS);
//         }

//         if(_depositPool == SWERVE_DEPOSIT_ADDRESS) {
//             uint[4] memory uamounts;
//             uamounts[0] = amount;
//             Deposit4Tokens(_depositPool).add_liquidity(uamounts, 0);
//             return (SRW_TOKEN_ADDRESS, SWERVE_GAUGE_ADDRESS);
//         }
//     }
// }
设置
{
  "compilationTarget": {
    "browser/Untitled.sol": "FirstDerivative"
  },
  "evmVersion": "istanbul",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]