账户
0x0a...8d25
SHUF-BSOV

SHUF-BSOV

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.5.12+commit.7709ece9
语言
Solidity
合同源代码
文件 1 的 1:DefswapExchange.sol
// File: contracts/interfaces/IERC20.sol

pragma solidity ^0.5.12;


interface IERC20 {
    /*
     * Metadata
     */
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint256);

    /**
     * @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 Only used on BASE token
     */
    function transferFromWithFee(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Only used on BASE token
     */
    function transferWithFee(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);
}

// File: contracts/interfaces/IUniswapExchange.sol

pragma solidity ^0.5.12;


interface IUniswapExchange {
    // Address of ERC20 token sold on this exchange
    function tokenAddress() external view returns (address token);
    // Address of Uniswap Factory
    function factoryAddress() external view returns (address factory);
    // Provide Liquidity
    function addLiquidity(uint256 min_liquidity, uint256 max_tokens, uint256 deadline) external payable returns (uint256);
    function removeLiquidity(uint256 amount, uint256 min_eth, uint256 min_tokens, uint256 deadline) external returns (uint256, uint256);
    // Get Prices
    function getEthToTokenInputPrice(uint256 eth_sold) external view returns (uint256 tokens_bought);
    function getEthToTokenOutputPrice(uint256 tokens_bought) external view returns (uint256 eth_sold);
    function getTokenToEthInputPrice(uint256 tokens_sold) external view returns (uint256 eth_bought);
    function getTokenToEthOutputPrice(uint256 eth_bought) external view returns (uint256 tokens_sold);
    // Trade ETH to ERC20
    function ethToTokenSwapInput(uint256 min_tokens, uint256 deadline) external payable returns (uint256  tokens_bought);
    function ethToTokenTransferInput(uint256 min_tokens, uint256 deadline, address recipient) external payable returns (uint256  tokens_bought);
    function ethToTokenSwapOutput(uint256 tokens_bought, uint256 deadline) external payable returns (uint256  eth_sold);
    function ethToTokenTransferOutput(uint256 tokens_bought, uint256 deadline, address recipient) external payable returns (uint256  eth_sold);
    // Trade ERC20 to ETH
    function tokenToEthSwapInput(uint256 tokens_sold, uint256 min_eth, uint256 deadline) external returns (uint256  eth_bought);
    function tokenToEthTransferInput(uint256 tokens_sold, uint256 min_eth, uint256 deadline, address recipient) external returns (uint256  eth_bought);
    function tokenToEthSwapOutput(uint256 eth_bought, uint256 max_tokens, uint256 deadline) external returns (uint256  tokens_sold);
    function tokenToEthTransferOutput(uint256 eth_bought, uint256 max_tokens, uint256 deadline, address recipient) external returns (uint256  tokens_sold);
    // Trade ERC20 to ERC20
    function tokenToTokenSwapInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address token_addr) external returns (uint256  tokens_bought);
    function tokenToTokenTransferInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address recipient, address token_addr) external returns (uint256  tokens_bought);
    function tokenToTokenSwapOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address token_addr) external returns (uint256  tokens_sold);
    function tokenToTokenTransferOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address recipient, address token_addr) external returns (uint256  tokens_sold);
    // Trade ERC20 to Custom Pool
    function tokenToExchangeSwapInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address exchange_addr) external returns (uint256  tokens_bought);
    function tokenToExchangeTransferInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address recipient, address exchange_addr) external returns (uint256  tokens_bought);
    function tokenToExchangeSwapOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address exchange_addr) external returns (uint256  tokens_sold);
    function tokenToExchangeTransferOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address recipient, address exchange_addr) external returns (uint256  tokens_sold);
    // ERC20 comaptibility for liquidity tokens
    function transfer(address _to, uint256 _value) external returns (bool);
    function transferFrom(address _from, address _to, uint256 value) external returns (bool);
    function approve(address _spender, uint256 _value) external returns (bool);
    function allowance(address _owner, address _spender) external view returns (uint256);
    function balanceOf(address _owner) external view returns (uint256);
    function totalSupply() external view returns (uint256);
    // Never use
    function setup(address token_addr) external;
}

// File: contracts/utils/IsContract.sol

pragma solidity ^0.5.12;


library IsContract {
    function isContract(address _addr) internal view returns (bool) {
        bytes32 codehash;
        /* solium-disable-next-line */
        assembly { codehash := extcodehash(_addr) }
        return codehash != bytes32(0) && codehash != bytes32(0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470);
    }
}

// File: contracts/interfaces/IDefswapExchange.sol

pragma solidity ^0.5.12;


interface IDefswapExchange {
    function base() external view returns (IERC20);
    function token() external view returns (IERC20);
    function addLiquidity(uint256 _tokens, uint256 _maxBase) external returns (uint256);
    function removeLiquidity(uint256 _amount, uint256 _minBase, uint256 _minTokens) external returns (uint256, uint256);
    function ethToTokenSwapInput(uint256 _minTokens) external payable returns (uint256);
    function baseToTokenSwapInput(uint256 _amount, uint256 _minTokens) external returns (uint256);
    function baseToTokenTransferInput(uint256 _amount, uint256 _minTokens, address _recipient) external returns (uint256);
    function tokenToEthSwapInput(uint256 _amount, uint256 _minEth) external returns (uint256);
    function tokenToEthTransferInput(uint256 _amount, uint256 _minEth, address _recipient) external returns (uint256);
    function tokenToEthExchangeTransferInput(uint256 _amount, uint256 _minTokens, address _recipient, address _exchangeAddr) external returns (uint256);
    function tokenToBaseSwapInput(uint256 _amount, uint256 _minBase) external returns (uint256);
    function tokenToBaseTransferInput(uint256 _amount, uint256 _minBase, address _recipient) external returns (uint256);
    function tokenToBaseExchangeTransferInput(uint256 _amount, uint256 _minTokens, address _recipient, address _exchangeAddr) external returns (uint256);
    // Uniswap exchange compat
    function ethToTokenTransferInput(uint256 _minTokens, uint256 _deadline, address _recipient) external payable returns (uint256);
}

// File: contracts/utils/ReentrancyGuard.sol

pragma solidity ^0.5.12;


/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 */
contract ReentrancyGuard {
    uint256 private _guardFlag;

    uint256 private constant FLAG_LOCK = 2;
    uint256 private constant FLAG_UNLOCK = 1;

    constructor () internal {
        // The flag starts at one to prevent changing it from zero to a non-zero
        // value, which is a more expensive operation.
        _guardFlag = FLAG_UNLOCK;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        require(_guardFlag != FLAG_LOCK, "reentrancy-guard: reentrant call");
        _guardFlag = FLAG_LOCK;
        _;
        _guardFlag = FLAG_UNLOCK;
    }
}

// File: contracts/utils/SafeMath.sol

pragma solidity ^0.5.12;


library SafeMath {
    function add(uint256 x, uint256 y) internal pure returns (uint256) {
        uint256 z = x + y;
        require(z >= x, "safemath: add overflow");
        return z;
    }

    function sub(uint256 x, uint256 y) internal pure returns (uint256) {
        require(x >= y, "safemath: sub overflow");
        return x - y;
    }

    function mul(uint256 x, uint256 y) internal pure returns (uint256) {
        if (x == 0) {
            return 0;
        }

        uint256 z = x * y;
        require(z / x == y, "safemath: mul overflow");
        return z;
    }

    function div(uint256 x, uint256 y) internal pure returns (uint256) {
        require(y != 0, "safemath: div by zero");
        return x / y;
    }

    function divRound(uint256 x, uint256 y) internal pure returns (uint256) {
        require(y != 0, "safemath: div by zero");
        uint256 z = x / y;
        if (x % y != 0) {
            z = z + 1;
        }

        return z;
    }
}

// File: contracts/commons/ERC20.sol

pragma solidity ^0.5.12;


contract ERC20 is IERC20 {
    using SafeMath for uint256;

    uint256 internal p_totalSupply;
    mapping(address => uint256) private p_balance;
    mapping(address => mapping(address => uint256)) private p_allowance;

    string private p_symbol;
    string private p_name;
    uint256 private p_decimals;

    function _setMetadata(
        string memory _symbol,
        string memory _name,
        uint256 _decimals
    ) internal {
        p_symbol = _symbol;
        p_name = _name;
        p_decimals = _decimals;
    }

    function symbol() external view returns (string memory) {
        return p_symbol;
    }

    function name() external view returns (string memory) {
        return p_name;
    }

    function decimals() external view returns (uint256) {
        return p_decimals;
    }

    function totalSupply() external view returns (uint256) {
        return p_totalSupply;
    }

    function balanceOf(address _addr) external view returns (uint256) {
        return p_balance[_addr];
    }

    function allowance(address _addr, address _spender) external view returns (uint256) {
        return p_allowance[_addr][_spender];
    }

    function approve(address _spender, uint256 _wad) external returns (bool) {
        emit Approval(msg.sender, _spender, _wad);
        p_allowance[msg.sender][_spender] = _wad;
        return true;
    }

    function transfer(address _to, uint256 _wad) external returns (bool) {
        _transfer(msg.sender, _to, _wad);
        return true;
    }

    function transferWithFee(address _to, uint256 _wad) external returns (bool) {
        _transfer(msg.sender, _to, _wad);
        return true;
    }

    function transferFrom(address _from, address _to, uint256 _wad) external returns (bool) {
        _transfer(_from, _to, _wad);
        return true;
    }

    function transferFromWithFee(address _from, address _to, uint256 _wad) external returns (bool) {
        _transfer(_from, _to, _wad);
        return true;
    }

    function _mint(
        address _to,
        uint256 _wad
    ) internal {
        p_totalSupply = p_totalSupply.add(_wad);
        p_balance[_to] = p_balance[_to].add(_wad);

        emit Transfer(address(0), _to, _wad);
    }

    function _burn(
        address _from,
        uint256 _wad
    ) internal {
        uint256 balance = p_balance[_from];
        require(balance >= _wad, "erc20: burn _from balance is not enough");
        p_balance[_from] = balance.sub(_wad);
        p_totalSupply = p_totalSupply.sub(_wad);
        emit Transfer(_from, address(0), _wad);
    }

    function _transfer(
        address _from,
        address _to,
        uint256 _wad
    ) private {
        if (msg.sender != _from) {
            uint256 t_allowance = p_allowance[_from][msg.sender];
            if (t_allowance != uint(-1)) {
                require(t_allowance >= _wad, "erc20: sender allowance is not enough");
                p_allowance[_from][msg.sender] = t_allowance.sub(_wad);
            }
        }

        uint256 fromBalance = p_balance[_from];
        require(fromBalance >= _wad, "erc20: transfer _from balance is not enough");
        p_balance[_from] = fromBalance.sub(_wad);
        p_balance[_to] = p_balance[_to].add(_wad);

        emit Transfer(_from, _to, _wad);
    }
}

// File: contracts/utils/SafeDefERC20.sol

pragma solidity ^0.5.12;


library SafeDefERC20 {
    using SafeMath for uint256;

    function safeTransfer(
        IERC20 _token,
        address _to,
        uint256 _wad
    ) internal returns (uint256) {
        uint256 prev = _token.balanceOf(address(this));

        (bool success, ) = address(_token).call(
            abi.encodeWithSelector(
                _token.transfer.selector,
                _to,
                _wad
            )
        );

        require(success, "safedeferc20: error sending tokens");
        return prev.sub(_token.balanceOf(address(this)));
    }

    function safeTransferFrom(
        IERC20 _token,
        address _from,
        address _to,
        uint256 _wad
    ) internal returns (uint256) {
        uint256 prev = _token.balanceOf(_to);

        (bool success, ) = address(_token).call(
            abi.encodeWithSelector(
                _token.transferFrom.selector,
                _from,
                _to,
                _wad
            )
        );

        require(success, "safedeferc20: error pulling tokens");
        return _token.balanceOf(_to).sub(prev);
    }
}

// File: contracts/utils/ShufUtils.sol

pragma solidity ^0.5.12;


library ShufUtils {
    using SafeMath for uint256;

    function takeFee(uint256 _a) internal pure returns (uint256) {
        if (_a == 1) {
            return 0;
        }

        uint256 fee = _a / 100;
        if (_a % 100 != 0) {
            fee = fee + 1;
        }

        return _a - (fee * 2);
    }

    function untakeFee(uint256 _a) internal pure returns (uint256) {
        if (_a == 1) {
            return 3;
        }

        uint256 aux = _a / 49;
        if (aux % 2 == 0) {
            aux = _a.add(aux);
            if (aux % 100 == 0) {
                return aux;
            } else {
                return aux.add(2);
            }
        } else {
            return _a.add(aux).add(1);
        }
    }
}

// File: contracts/DefswapExchange.sol

pragma solidity ^0.5.12;


contract DefswapExchange is IDefswapExchange, ERC20, ReentrancyGuard {
    using SafeDefERC20 for IERC20;
    using SafeMath for uint256;

    IERC20 private p_base;
    IERC20 private p_token;
    IUniswapExchange private p_uniswap;

    string private constant SYMBOL_PREFIX = "SHUF-";
    string private constant NAME_SUFIX = " - defswap.io pooled";
    uint256 private constant DECIMALS = 18;

    event AddLiquidity(
        address indexed _provider,
        uint256 _baseAmount,
        uint256 _tokenAmount,
        uint256 _minted
    );

    event RemoveLiquidity(
        address indexed _provider,
        uint256 _baseAmount,
        uint256 _tokenAmount,
        uint256 _burned,
        uint256 _type
    );

    event TokenPurchase(
        address indexed _buyer,
        uint256 _baseSold,
        uint256 _tokensBought,
        uint256 _baseReserve,
        uint256 _tokenReserve,
        address _recipient
    );

    event BasePurchase(
        address indexed _buyer,
        uint256 _tokensSold,
        uint256 _baseBought,
        uint256 _tokenReserve,
        uint256 _baseReserve,
        address _recipient
    );

    constructor(IERC20 _base, IERC20 _token, IUniswapExchange _uniswap) public {
        require(_uniswap.tokenAddress() == address(_base), "defswap: uniswap token doesn't match");
        require(address(_base) != address(_token), "defswap: token and base can't be the same");

        p_base = _base;
        p_token = _token;
        p_uniswap = _uniswap;

        approveUniswap();
        buildMetadata();
    }

    function approveUniswap() public nonReentrant {
        p_base.approve(
            address(p_uniswap),
            uint(-1)
        );
    }

    function buildMetadata() public nonReentrant {
        address token = address(p_token);
        require(gasleft() >= 402000, "defswap: gasleft build metadata is not enough");

        (
            bool successName,
            bytes memory name
        ) = token.staticcall(
            abi.encodeWithSelector(p_token.name.selector)
        );

        (
            bool successSymbol,
            bytes memory symbol
        ) = token.staticcall(
            abi.encodeWithSelector(p_token.symbol.selector)
        );

        _setMetadata(
            string(abi.encodePacked(SYMBOL_PREFIX, successSymbol ? abi.decode(symbol, (string)) : "???")),
            string(abi.encodePacked(successName ? abi.decode(name, (string)) : "Unknown", NAME_SUFIX)),
            DECIMALS
        );
    }

    function base() external view returns (IERC20) {
        return p_base;
    }

    function token() external view returns (IERC20) {
        return p_token;
    }

    function uniswap() external view returns (IUniswapExchange) {
        return p_uniswap;
    }

    function addLiquidity(
        uint256 _tokens,
        uint256 _maxBase
    ) external nonReentrant returns (uint256 minted) {
        IERC20 t_token = p_token;
        IERC20 t_base = p_base;

        // Pull tokens and store them in pool
        // received stores the real amount of received tokens
        uint256 received = t_token.safeTransferFrom(msg.sender, address(this), _tokens);
        require(received != 0, "defswap: pull zero tokens is not allowed");

        uint256 baseReceived;
        uint256 t_totalSupply = p_totalSupply;

        // Check if this is the first pool
        if (t_totalSupply == 0) {
            // Pull all _maxBase and mint received
            require(t_base.transferFrom(msg.sender, address(this), _maxBase), "defswap: error pulling base tokens");
            baseReceived = ShufUtils.takeFee(_maxBase);
            minted = baseReceived;
        } else {
            // Calculate required pull, following current pool rate
            uint256 tokenReserve = t_token.balanceOf(address(this)).sub(received);
            uint256 baseReserve = t_base.balanceOf(address(this));
            uint256 requiredPull = received.mul(baseReserve).divRound(tokenReserve);

            // Pull tokens after untaking fee
            baseReceived = t_base.safeTransferFrom(msg.sender, address(this), ShufUtils.untakeFee(requiredPull));
            require(baseReceived <= _maxBase, "defswap: _maxBase is below of pulled required");
            require(baseReceived >= requiredPull, "defswap: pulled base is not enough");

            // Mint proportional tokens
            minted = baseReceived.mul(t_totalSupply).div(baseReserve);
        }

        // Mint tokens and event
        emit AddLiquidity(msg.sender, baseReceived, received, minted);
        _mint(msg.sender, minted);
    }

    function removeLiquidity(
        uint256 _amount,
        uint256 _minBase,
        uint256 _minTokens
    ) external nonReentrant returns (
        uint256 baseAmount,
        uint256 tokenAmount
    ) {
        // Load totalSupply and check that it's not zero
        uint256 t_totalSupply = p_totalSupply;
        require(t_totalSupply != 0, "defswap: pool is empty");

        // Load token contracts
        IERC20 t_token = p_token;
        IERC20 t_base = p_base;

        // Load token reserves
        uint256 tokenReserve = t_token.balanceOf(address(this));
        uint256 baseReserve = t_base.balanceOf(address(this));

        // Calculate base and tokens to withdraw
        baseAmount = _amount.mul(baseReserve) / t_totalSupply;
        tokenAmount = _amount.mul(tokenReserve) / t_totalSupply;

        // Emit event and remove burn tokens from sender
        emit RemoveLiquidity(msg.sender, baseAmount, tokenAmount, _amount, 0);
        _burn(msg.sender, _amount);

        // Check if taken base if above _minBase
        require(baseAmount >= _minBase, "defswap: baseAmount is below _minBase");

        // Transfer tokens and base
        require(t_token.safeTransfer(msg.sender, tokenAmount) >= _minTokens, "defswap: tokenAmount is below _minTokens");
        t_base.transferWithFee(msg.sender, baseAmount); // t_base is trusted
    }

    function removeBaseLiquidity(
        uint256 _amount,
        uint256 _minBase
    ) external nonReentrant returns (
        uint256 baseAmount
    ) {
        // Load totalSupply and check that it's not zero
        uint256 t_totalSupply = p_totalSupply;
        require(t_totalSupply != 0, "defswap: pool is empty");

        // Load token contract
        IERC20 t_base = p_base;

        // Load base reserve
        uint256 baseReserve = t_base.balanceOf(address(this));

        // Calculate base to withdraw
        baseAmount = _amount.mul(baseReserve) / t_totalSupply;

        // Burn tokens and emit event
        // it burns the full _amount
        emit RemoveLiquidity(msg.sender, baseAmount, 0, _amount, 1);
        _burn(msg.sender, _amount);

        // Check if withdraw base is above _minBase and transfer tokens
        require(baseAmount >= _minBase, "defswap: baseAmount is below _minBase");
        t_base.transferWithFee(msg.sender, baseAmount); // t_base is trusted
    }

    function removeTokenLiquidity(
        uint256 _amount,
        uint256 _minTokens
    ) external nonReentrant returns (
        uint256 tokenAmount
    ) {
        // Load totalSupply and check that it's not zero
        uint256 t_totalSupply = p_totalSupply;
        require(t_totalSupply != 0, "defswap: pool is empty");

        // Load token contract
        IERC20 t_token = p_token;

        // Load token reserve
        uint256 tokenReserve = t_token.balanceOf(address(this));

        // Calculate token to withdraw
        tokenAmount = _amount.mul(tokenReserve) / t_totalSupply;

        // Burn tokens and emit event
        // it burns the full _amount
        emit RemoveLiquidity(msg.sender, 0, tokenAmount, _amount, 2);
        _burn(msg.sender, _amount);

        // Transfer tokens and check if withdrawn amount is above _minTokens
        require(t_token.safeTransfer(msg.sender, tokenAmount) >= _minTokens, "defswap: tokenAmount is below _minTokens");
    }

    function getBaseToTokenPrice(uint256 _baseSold) external view returns (uint256 tokensBought) {
        tokensBought = _getInputPrice(
            _baseSold,
            p_base.balanceOf(address(this)),
            p_token.balanceOf(address(this))
        );
    }

    function getTokenToBasePrice(uint256 _tokenSold) external view returns (uint256 baseBought) {
        baseBought = _getInputPrice(
            _tokenSold,
            p_token.balanceOf(address(this)),
            p_base.balanceOf(address(this))
        );
    }

    function ethToTokenSwapInput(
        uint256 _minTokens
    ) external nonReentrant payable returns (uint256 bought) {
        // Trade ETH -> BASE, only if msg.value is not zero
        uint256 baseBought = msg.value != 0 ? ShufUtils.takeFee(
            p_uniswap.ethToTokenSwapInput.value(msg.value)(1, uint(-1))
        ) : 0;

        // Trade BASE -> TOKEN, and transfer to sender
        bought = _baseToToken(
            p_base,     // Base address
            p_token,    // Token address
            baseBought, // Base bought on trade ETH -> BASE
            _minTokens, // Min base to receive
            msg.sender, // Origin of the trade
            msg.sender  // Recipient of the tokens
        );
    }

    // Uniswap exchange compat
    function ethToTokenTransferInput(
        uint256 _minTokens,
        uint256 _deadline,
        address _recipient
    ) external nonReentrant payable returns (uint256 bought) {
        // Check if _deadile was exceeded
        require(_deadline >= block.timestamp, "defswap: expired transaction");

        // Trade ETH -> BASE, only if msg.value is not zero
        uint256 baseBought = msg.value != 0 ? ShufUtils.takeFee(
            p_uniswap.ethToTokenSwapInput.value(msg.value)(1, uint(-1))
        ) : 0;

        // Trade BASE -> TOKEN, and transfer to _recipient
        bought = _baseToToken(
            p_base,     // Base address
            p_token,    // Token address
            baseBought, // Base bought on trade ETH -> BASE
            _minTokens, // Min base to receive
            msg.sender, // Origin of the trade
            _recipient  // Recipient of the tokens
        );
    }

    function baseToTokenSwapInput(
        uint256 _amount,
        uint256 _minTokens
    ) external nonReentrant returns (uint256 bought) {
        // Load base contract
        IERC20 t_base = p_base;

        // Transfer base from msg.sender to this
        t_base.transferFromWithFee(msg.sender, address(this), _amount);
        // real received has to take into account the transfer fee
        uint256 received = ShufUtils.takeFee(_amount);

        // Trade BASE -> TOKEN, and transfer to msg.sender
        bought = _baseToToken(
            t_base,     // Base address (already loaded)
            p_token,    // Token address
            received,   // Base received from msg.sender
            _minTokens, // Min tokens to buy
            msg.sender, // Origin of the trade
            msg.sender  // Recipient of the tokens
        );
    }

    function baseToTokenTransferInput(
        uint256 _amount,
        uint256 _minTokens,
        address _recipient
    ) external nonReentrant returns (uint256 bought) {
        // Load base contract
        IERC20 t_base = p_base;

        // Transfer base from msg.sender to this
        t_base.transferFromWithFee(msg.sender, address(this), _amount);
        // real received has to take into account the transfer fee
        uint256 received = ShufUtils.takeFee(_amount);

        // Trade BASE -> TOKEN, and transfer to msg.sender
        bought = _baseToToken(
            t_base,     // Base address (already loaded)
            p_token,    // Token address
            received,   // Base received from msg.sender
            _minTokens, // Min tokens to buy
            msg.sender, // Origin of the trade
            _recipient  // Recipient of the tokens
        );
    }

    function tokenToEthSwapInput(
        uint256 _amount,
        uint256 _minEth
    ) external nonReentrant returns (uint256 bought) {
        // Load token contract from storage
        IERC20 t_token = p_token;

        // Transfer tokens from sender to this
        // and store the real amount of received tokens
        uint256 received = t_token.safeTransferFrom(msg.sender, address(this), _amount);

        // Convert TOKEN -> BASE and send base to this
        // to later be converted into ETH
        uint256 baseBought = ShufUtils.takeFee(
            _tokenToBase(
                p_base,       // Base address (already loaded)
                t_token,      // Token address (already loaded)
                received,     // Received tokens from msg.sender
                0,            // Min base to buy (zero, will check the final result)
                msg.sender,   // Origin of the trade
                address(this) // Recipent of the base (self)
            )
        );

        // Convert BASE -> ETH if baseBought is not zero
        bought = baseBought != 0 ? p_uniswap.tokenToEthTransferInput(
            baseBought, // Base amount to convert
            1,          // Min ETH to buy (1, will check later using require)
            uint(-1),   // Trade expiration (never)
            msg.sender  // Recipent of the ETH
        ) : 0;

        // Check if bought ETH is above _minEth
        require(bought >= _minEth, "defswap: eth bought is below _minEth");
    }

    function tokenToEthTransferInput(
        uint256 _amount,
        uint256 _minEth,
        address _recipient
    ) external nonReentrant returns (uint256 bought) {
        // Load token contract from storage
        IERC20 t_token = p_token;

        // Transfer tokens from sender to this
        // and store the real amount of received tokens
        uint256 received = t_token.safeTransferFrom(msg.sender, address(this), _amount);

        // Convert TOKEN -> BASE and send base to this
        // to later be converted into ETH
        uint256 baseBought = ShufUtils.takeFee(
            _tokenToBase(
                p_base,       // Base address (already loaded)
                t_token,      // Token address (already loaded)
                received,     // Received tokens from msg.sender
                0,            // Min base to buy (zero, will check the final result)
                msg.sender,   // Origin of the trade
                address(this) // Recipent of the base (self)
            )
        );

        // Convert BASE -> ETH if baseBought is not zero
        bought = baseBought != 0 ? p_uniswap.tokenToEthTransferInput(
            baseBought, // Base amount to convert
            1,          // Min ETH to buy (1, will check later using require)
            uint(-1),   // Trade expiration (never)
            _recipient  // Recipent of the ETH
        ) : 0;

        // Check if bought ETH is above _minEth
        require(bought >= _minEth, "defswap: eth bought is below _minEth");
    }

    function tokenToEthExchangeTransferInput(
        uint256 _amount,
        uint256 _minTokens,
        address _recipient,
        address _exchangeAddr
    ) external nonReentrant returns (uint256 bought) {
        // Load token contract from storage
        IERC20 t_token = p_token;

        // Transfer tokens from sender to this
        // and store the real amount of received tokens
        uint256 received = t_token.safeTransferFrom(msg.sender, address(this), _amount);

        // Convert TOKEN -> BASE and send base to this
        // to later be converted into ETH
        uint256 baseBought = ShufUtils.takeFee(
            _tokenToBase(
                p_base,       // Base address (already loaded)
                t_token,      // Token address (already loaded)
                received,     // Received tokens from msg.sender
                0,            // Min base to buy (zero, will check the final result)
                msg.sender,   // Origin of the trade
                address(this) // Recipent of the base (self)
            )
        );

        // Convert BASE -> ETH if baseBought is not zero
        // and transfer to self
        uint256 ethBought = baseBought != 0 ? p_uniswap.tokenToEthSwapInput(
            baseBought, // Base amount to sell
            1,          // Min ETH to buy (1, will be check later)
            uint(-1)    // Trade expiration (never)
        ) : 0;

        // Convert ETH -> TOKEN if ethBought is not zero
        bought = ethBought != 0 ? IUniswapExchange(_exchangeAddr).ethToTokenTransferInput.value(
            ethBought   // ETH to sell
        )(
            1,          // Min token buy (1, will check later)
            uint(-1),   // Trade expiration (never)
            _recipient  // Recipient of the tokens
        ) : 0;

        // Check if bought tokens is above _minTokens
        // _exchangeAddr is considered trusted and it may never have transfered
        // the ETH to the _recipient, this code trusts the return value of _exchangeAddr.ethToTokenTransferInput
        require(bought >= _minTokens, "defswap: tokens bought is below _minTokens");
    }

    function tokenToBaseSwapInput(
        uint256 _amount,
        uint256 _minBase
    ) external nonReentrant returns (uint256 bought) {
        // Load token contract from storage
        IERC20 t_token = p_token;

        // Transfer tokens from sender to this
        // and store the real amount of received tokens
        uint256 received = t_token.safeTransferFrom(msg.sender, address(this), _amount);

        // Convert TOKEN -> BASE and send base to msg.sender
        bought = _tokenToBase(
            p_base,     // Base address (already loaded)
            t_token,    // Token address (already loaded)
            received,   // Tokens to sell (received from msg.sender)
            _minBase,   // Min base to buy
            msg.sender, // Origin of the trade
            msg.sender  // Recipient of the base
        );
    }

    function tokenToBaseTransferInput(
        uint256 _amount,
        uint256 _minBase,
        address _recipient
    ) external nonReentrant returns (uint256 bought) {
        // Load token contract from storage
        IERC20 t_token = p_token;

        // Transfer tokens from sender to this
        // and store the real amount of received tokens
        uint256 received = t_token.safeTransferFrom(msg.sender, address(this), _amount);

        // Convert TOKEN -> BASE and send base to _recipient
        bought = _tokenToBase(
            p_base,     // Base address (already loaded)
            t_token,    // Token address (already loaded)
            received,   // Tokens to sell (received from msg.sender)
            _minBase,   // Min base to buy
            msg.sender, // Origin of the trade
            _recipient  // Recipient of the base
        );
    }

    function tokenToBaseExchangeTransferInput(
        uint256 _amount,
        uint256 _minTokens,
        address _recipient,
        address _exchangeAddr
    ) external nonReentrant returns (uint256 bought) {
        // _exchangeAddr can't be uniswap
        // because that would remove the Uniswap approve made during the exchange creation
        require(_exchangeAddr != address(p_uniswap), "defswap: _exchange can't be Uniswap");

        // Load contracts from storage
        IERC20 t_token = p_token;
        IERC20 t_base = p_base;

        // Transfer tokens from sender to this
        // and store the real amount of received tokens
        uint256 received = t_token.safeTransferFrom(msg.sender, address(this), _amount);

        // Load token and base reserves
        uint256 tokenReserve = t_token.balanceOf(address(this)).sub(received);
        uint256 baseReserve = t_base.balanceOf(address(this));

        // Calculate baseBought, the trade it's not executed to avoid charging the transfer fee twice
        // this represents TOKEN_A -> BASE
        uint256 baseBought = _getInputPrice(received, tokenReserve, baseReserve);
        emit BasePurchase(msg.sender, received, baseBought, tokenReserve, baseReserve, _exchangeAddr);

        // Trade BASE -> TOKEN_B, using base baseBought with TOKEN_A
        // the exchange is approve to withdraw `baseBought` and the approve is removed after
        // the trade, _exchangeAddr can't exploit the temporal reserve ratio because of the reentrancy lock
        t_base.approve(_exchangeAddr, baseBought);
        bought = IDefswapExchange(_exchangeAddr).baseToTokenTransferInput(
            baseBought, // BASE tokens to sell
            _minTokens, // Min TOKEN_B to buy
            _recipient  // Recipeint of token b
        );

        // Always remove the approve after the trade
        t_base.approve(_exchangeAddr, 0);
    }

    function _getInputPrice(
        uint256 _inputAmount,
        uint256 _inputReserve,
        uint256 _outputReserve
    ) private pure returns (uint256) {
        require(_inputReserve != 0 && _outputReserve != 0, "defswap: one reserve is empty");
        uint256 inputAmountWithFee = _inputAmount.mul(997);
        uint256 numerator = inputAmountWithFee.mul(_outputReserve);
        uint256 denominator = _inputReserve.mul(1000).add(inputAmountWithFee);
        return numerator / denominator;
    }

    function _baseToToken(
        IERC20 t_base,
        IERC20 t_token,
        uint256 _amount,
        uint256 _minTokens,
        address _buyer,
        address _recipient
    ) private returns (uint256 tokensBought) {
        // Load base and token reserves
        uint256 tokenReserve = t_token.balanceOf(address(this));
        uint256 baseReserve = t_base.balanceOf(address(this)).sub(_amount);

        // Calculate tokens bought
        tokensBought = _getInputPrice(_amount, baseReserve, tokenReserve);

        // Check if tokens bought is above _minTokens and execute transfer
        require(tokensBought >= _minTokens, "defswap: bought tokens below _minTokens");
        require(t_token.safeTransfer(_recipient, tokensBought) != 0 || tokensBought == 0, "defswap: error sending tokens");

        emit TokenPurchase(_buyer, _amount, tokensBought, baseReserve, tokenReserve, _recipient);
    }

    function _tokenToBase(
        IERC20 t_base,
        IERC20 t_token,
        uint256 _amount,
        uint256 _minBase,
        address _buyer,
        address _recipient
    ) private returns (uint256 baseBought) {
        // Load base and token reserves
        uint256 tokenReserve = t_token.balanceOf(address(this)).sub(_amount);
        uint256 baseReserve = t_base.balanceOf(address(this));

        // Calculate base bought
        baseBought = _getInputPrice(_amount, tokenReserve, baseReserve);

        // Check if base bought is above _minBase and execute transfer
        require(baseBought >= _minBase, "defswap: bought base below _minBase");
        t_base.transferWithFee(_recipient, baseBought);

        emit BasePurchase(_buyer, _amount, baseBought, tokenReserve, baseReserve, _recipient);
    }

    function() external payable {
        // Revert if an EOA send's ETH
        require(msg.sender != tx.origin, "defswap: ETH rejected");
    }
}

// File: contracts/DefswapFactory.sol

pragma solidity ^0.5.12;


contract DefswapFactory {
    using IsContract for address;

    IUniswapExchange public uniswap;
    IERC20 public base;

    event CreatedExchange(address indexed _token, address indexed _exchange);

    address[] private p_tokens;
    mapping(address => address) public tokenToExchange;
    mapping(address => address) public exchangeToToken;

    constructor(IERC20 _base, IUniswapExchange _uniswap) public {
        require(_uniswap.tokenAddress() == address(_base), "defswap-factory: uniswap token doesn't match");

        base = _base;
        uniswap = _uniswap;
    }

    function getToken(uint256 _i) external view returns (address) {
        require(_i < p_tokens.length, "defswap-factory: array out of bounds");
        return p_tokens[_i];
    }

    function getExchange(uint256 _i) external view returns (address) {
        require(_i < p_tokens.length, "defswap-factory: array out of bounds");
        return tokenToExchange[p_tokens[_i]];
    }

    function createExchange(address _token) external returns (address exchange) {
        require(tokenToExchange[_token] == address(0), "defswap-factory: exchange already exists");
        require(_token.isContract(), "defswap-factory: _token has to be a contract");

        exchange = address(
            new DefswapExchange(
                base,
                IERC20(_token),
                uniswap
            )
        );

        emit CreatedExchange(_token, exchange);

        tokenToExchange[_token] = exchange;
        exchangeToToken[exchange] = _token;
        p_tokens.push(_token);
    }
}
设置
{
  "compilationTarget": {
    "DefswapExchange.sol": "DefswapExchange"
  },
  "evmVersion": "petersburg",
  "libraries": {},
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"inputs":[{"internalType":"contract IERC20","name":"_base","type":"address"},{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"contract IUniswapExchange","name":"_uniswap","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"_baseAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_minted","type":"uint256"}],"name":"AddLiquidity","type":"event"},{"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":"_buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"_tokensSold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_baseBought","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_tokenReserve","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_baseReserve","type":"uint256"},{"indexed":false,"internalType":"address","name":"_recipient","type":"address"}],"name":"BasePurchase","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"_baseAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_burned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_type","type":"uint256"}],"name":"RemoveLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"_baseSold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_tokensBought","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_baseReserve","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_tokenReserve","type":"uint256"},{"indexed":false,"internalType":"address","name":"_recipient","type":"address"}],"name":"TokenPurchase","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"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_tokens","type":"uint256"},{"internalType":"uint256","name":"_maxBase","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"minted","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_addr","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_wad","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"approveUniswap","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"base","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minTokens","type":"uint256"}],"name":"baseToTokenSwapInput","outputs":[{"internalType":"uint256","name":"bought","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minTokens","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"baseToTokenTransferInput","outputs":[{"internalType":"uint256","name":"bought","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"buildMetadata","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_minTokens","type":"uint256"}],"name":"ethToTokenSwapInput","outputs":[{"internalType":"uint256","name":"bought","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_minTokens","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"ethToTokenTransferInput","outputs":[{"internalType":"uint256","name":"bought","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_baseSold","type":"uint256"}],"name":"getBaseToTokenPrice","outputs":[{"internalType":"uint256","name":"tokensBought","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_tokenSold","type":"uint256"}],"name":"getTokenToBasePrice","outputs":[{"internalType":"uint256","name":"baseBought","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minBase","type":"uint256"}],"name":"removeBaseLiquidity","outputs":[{"internalType":"uint256","name":"baseAmount","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minBase","type":"uint256"},{"internalType":"uint256","name":"_minTokens","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"baseAmount","type":"uint256"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minTokens","type":"uint256"}],"name":"removeTokenLiquidity","outputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minTokens","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"address","name":"_exchangeAddr","type":"address"}],"name":"tokenToBaseExchangeTransferInput","outputs":[{"internalType":"uint256","name":"bought","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minBase","type":"uint256"}],"name":"tokenToBaseSwapInput","outputs":[{"internalType":"uint256","name":"bought","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minBase","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"tokenToBaseTransferInput","outputs":[{"internalType":"uint256","name":"bought","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minTokens","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"address","name":"_exchangeAddr","type":"address"}],"name":"tokenToEthExchangeTransferInput","outputs":[{"internalType":"uint256","name":"bought","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minEth","type":"uint256"}],"name":"tokenToEthSwapInput","outputs":[{"internalType":"uint256","name":"bought","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minEth","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"tokenToEthTransferInput","outputs":[{"internalType":"uint256","name":"bought","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_wad","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_wad","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_wad","type":"uint256"}],"name":"transferFromWithFee","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_wad","type":"uint256"}],"name":"transferWithFee","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"uniswap","outputs":[{"internalType":"contract IUniswapExchange","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]