contract ERC20SwappableInput is ERC20, Ownable {
    using SafeMath for uint256;

    /**
     * @dev Emitted when funds have been burned and queued for swapping to another token.
     */
    event SwapInput(address indexed outputToken, address indexed payee, uint256 inputAmount, uint256 outputAmount);

    /**
     * @dev Swaps funds to another token.
     * @param outputToken The output ERC20SwappableOutput token contract address.
     * @param payee The address to which the output funds will be sent.
     * @param inputAmount The amount of input tokens to be burned.
     */
    function swap(address outputToken, address payee, uint256 inputAmount) external returns (bool) {
        require(_outputSwapTokens[outputToken] != 0, "Output token is not a registered output swap token.");
        require(inputAmount > 0, "No funds inputted to swap.");
        require(inputAmount <= this.balanceOf(payee), "Input amount cannot be greater than input token balance.");
        require(_outputSwapTokens[outputToken] < 0 || inputAmount <= uint256(_outputSwapTokens[outputToken]), "Input amount is greater than the limit for this output token.");
        ERC20SwappableOutput outputContract = ERC20SwappableOutput(outputToken);
        uint256 outputTotalSupply = outputContract.totalSupply();
        require(outputTotalSupply > 0, "Cannot reference zero total supply of output tokens when calculating output token amount.");
        uint256 outputAmount = inputAmount.mul(outputTotalSupply).div(this.totalSupply());
        _burn(msg.sender, inputAmount);
        require(outputContract.finishSwap(msg.sender, inputAmount, outputAmount), "Failed to finish swap with output token.");
        emit SwapInput(msg.sender, payee, inputAmount, outputAmount);
        return true;
    }

    mapping(address => int256) private _outputSwapTokens;

    /**
     * @dev Registers an output swap token.
     * @param token The address of the token.
     */
    function addOutputSwapToken(address token, uint256 limit) external onlyOwner returns (bool) {
        _outputSwapTokens[token] = limit > 0 ? int256(limit) : -1;
        return true;
    }

    /**
     * @dev Unregisters an output swap token.
     * @param token The address of the token.
     */
    function removeOutputSwapToken(address token) external onlyOwner returns (bool) {
        _outputSwapTokens[token] = 0;
        return true;
    }
}
/**
 * @title ERC20SwappableInput
 * @dev ERC20 token that can be converted to another ERC20 token.
 */
function addOutputSwapToken(address token, uint256 limit) external onlyOwner returns (bool) {
        _outputSwapTokens[token] = limit > 0 ? int256(limit) : -1;
        return true;
    }
/**
 * @dev Registers an output swap token.
 * @param token The address of the token.
 */