library SafeERC20 {

    using SafeMath for uint256;

    /**
    * @dev Transfer token for a specified address
    * @param _token erc20 The address of the ERC20 contract
    * @param _to address The address which you want to transfer to
    * @param _value uint256 the _value of tokens to be transferred
    * @return bool whether the transfer was successful or not
    */
    function safeTransfer(IERC20 _token, address _to, uint256 _value) internal returns (bool) {
        uint256 prevBalance = _token.balanceOf(address(this));

        if (prevBalance < _value) {
            // Insufficient funds
            return false;
        }

        address(_token).call(
            abi.encodeWithSignature("transfer(address,uint256)", _to, _value)
        );

        if (prevBalance.sub(_value) != _token.balanceOf(address(this))) {
            // Transfer failed
            return false;
        }

        return true;
    }

    /**
    * @dev Transfer tokens from one address to another
    * @param _token erc20 The address of the ERC20 contract
    * @param _from address The address which you want to send tokens from
    * @param _to address The address which you want to transfer to
    * @param _value uint256 the _value of tokens to be transferred
    * @return bool whether the transfer was successful or not
    */
    function safeTransferFrom(
        IERC20 _token,
        address _from,
        address _to,
        uint256 _value
    ) internal returns (bool)
    {
        uint256 prevBalance = _token.balanceOf(_from);

        if (prevBalance < _value) {
            // Insufficient funds
            return false;
        }

        if (_token.allowance(_from, address(this)) < _value) {
            // Insufficient allowance
            return false;
        }

        address(_token).call(
            abi.encodeWithSignature("transferFrom(address,address,uint256)", _from, _to, _value)
        );

        if (prevBalance.sub(_value) != _token.balanceOf(_from)) {
            // Transfer failed
            return false;
        }

        return true;
    }

    /**
    * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
    *
    * 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
    *
    * @param _token erc20 The address of the ERC20 contract
    * @param _spender The address which will spend the funds.
    * @param _value The amount of tokens to be spent.
    * @return bool whether the approve was successful or not
    */
    function safeApprove(IERC20 _token, address _spender, uint256 _value) internal returns (bool) {
        address(_token).call(
            abi.encodeWithSignature("approve(address,uint256)", _spender, _value)
        );

        if (_token.allowance(address(this), _spender) != _value) {
            // Approve failed
            return false;
        }

        return true;
    }

}
/**
 * @dev Library to perform safe calls to standard method for ERC20 tokens.
 *
 * Why Transfers: transfer methods could have a return value (bool), throw or revert for insufficient funds or
 * unathorized value.
 *
 * Why Approve: approve method could has a return value (bool) or does not accept 0 as a valid value (BNB token).
 * The common strategy used to clean approvals.
 *
 * We use the Solidity call instead of interface methods because in the case of transfer, it will fail
 * for tokens with an implementation without returning a value.
 * Since versions of Solidity 0.4.22 the EVM has a new opcode, called RETURNDATASIZE.
 * This opcode stores the size of the returned data of an external call. The code checks the size of the return value
 * after an external call and reverts the transaction in case the return data is shorter than expected
 */
function safeApprove(IERC20 _token, address _spender, uint256 _value) internal returns (bool) {
    address(_token).call(
        abi.encodeWithSignature("approve(address,uint256)", _spender, _value)
    );

    if (_token.allowance(address(this), _spender) != _value) {
        // Approve failed
        return false;
    }

    return true;
}

/**
 * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
 *
 * 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
 *
 * @param _token erc20 The address of the ERC20 contract
 * @param _spender The address which will spend the funds.
 * @param _value The amount of tokens to be spent.
 * @return bool whether the approve was successful or not
 */