ETH Price: $2,975.68 (-2.47%)

Transaction Decoder

Block:
22019334 at Mar-10-2025 10:04:35 PM +UTC
Transaction Fee:
0.000456186649318785 ETH $1.36
Gas Used:
166,677 Gas / 2.736950205 Gwei

Emitted Events:

83 Dai.Transfer( src=[Sender] 0xe5c2d742d87643031bec4a171f92c5341a59baa4, dst=0x85CD07Ea01423b1E937929B44E4Ad8c40BbB5E71, wad=99947861197947667672 )
84 WBTC.Transfer( from=0x391E8501b626C623d39474AfcA6f9e46c2686649, to=0x85CD07Ea01423b1E937929B44E4Ad8c40BbB5E71, value=125468 )
85 Dai.Transfer( src=0x85CD07Ea01423b1E937929B44E4Ad8c40BbB5E71, dst=0x391E8501b626C623d39474AfcA6f9e46c2686649, wad=99947861197947667672 )
86 0x391e8501b626c623d39474afca6f9e46c2686649.0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67( 0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67, 0x00000000000000000000000085cd07ea01423b1e937929b44e4ad8c40bbb5e71, 0x00000000000000000000000085cd07ea01423b1e937929b44e4ad8c40bbb5e71, fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe15e4, 0000000000000000000000000000000000000000000000056b0e22368bb804d8, 0000000000000000000000000000000001ae0a8012a5f1e6d86df299647c9825, 000000000000000000000000000000000000000000000000007b243b4bcb02d2, 0000000000000000000000000000000000000000000000000000000000053c3d )
87 0x85cd07ea01423b1e937929b44e4ad8c40bbb5e71.0x1bf1122521093cffed0b7f29833cd231d885bae58dceb074e411a1fbd94824bd( 0x1bf1122521093cffed0b7f29833cd231d885bae58dceb074e411a1fbd94824bd, 0x000000000000000000000000ad27827c312cd5e71311d68e180a9872d42de23d, 0x0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f, 0x0000000000000000000000000000000000000000000000000000000000000000, 00000000000000000000000085cd07ea01423b1e937929b44e4ad8c40bbb5e71, 0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599, 0000000000000000000000000000000000000000000000056b0e22368bb804d8, 000000000000000000000000000000000000000000000000000000000001e7a8, 000000000000000000000000000000000000000000000000000000000001ea1c, 0000000000000000000000000000000000000000000000000000000000000000 )
88 WBTC.Transfer( from=0x85CD07Ea01423b1E937929B44E4Ad8c40BbB5E71, to=TokenChomper, value=312 )
89 WBTC.Transfer( from=0x85CD07Ea01423b1E937929B44E4Ad8c40BbB5E71, to=[Sender] 0xe5c2d742d87643031bec4a171f92c5341a59baa4, value=125156 )

Account State Difference:

  Address   Before After State Difference Code
0x2260FAC5...93bc2C599
0x391E8501...6c2686649
(Uniswap V3: WBTC-DAI)
0x6B175474...495271d0F
(beaverbuild)
15.89886767495813584 Eth15.89902935164813584 Eth0.00016167669
0xe5C2d742...41a59bAA4
0.130204336241800066 Eth
Nonce: 7
0.129748149592481281 Eth
Nonce: 8
0.000456186649318785

Execution Trace

RedSnwapper.snwap( tokenIn=0x6B175474E89094C44Da98b954EedeAC495271d0F, amountIn=99947861197947667672, recipient=0xe5C2d742D87643031BEc4A171f92C5341a59bAA4, tokenOut=0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599, amountOutMin=124528, executor=0x85CD07Ea01423b1E937929B44E4Ad8c40BbB5E71, executorData=0xEE623204000000000000000000000000CA226BD9C754F1283123D32B2A7CF62A722F8ADA00000000000000000000000000000000000000000000000000000000000001380000000000000000000000006B175474E89094C44DA98B954EEDEAC495271D0F0000000000000000000000000000000000000000000000056B0E22368BB804D80000000000000000000000002260FAC5E5542A773AA44FBCFEDF7C193BC2C599000000000000000000000000000000000000000000000000000000000001EA1C000000000000000000000000000000000000000000000000000000000001E7A8000000000000000000000000E5C2D742D87643031BEC4A171F92C5341A59BAA4000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043016B175474E89094C44DA98B954EEDEAC495271D0F01FFFF01391E8501B626C623D39474AFCA6F9E46C26866490085CD07EA01423B1E937929B44E4AD8C40BBB5E71000000000000000000000000000000000000000000000000000000000000 ) => ( amountOut=125156 )
  • WBTC.balanceOf( _owner=0xe5C2d742D87643031BEc4A171f92C5341a59bAA4 ) => ( 108549 )
  • Dai.transferFrom( src=0xe5C2d742D87643031BEc4A171f92C5341a59bAA4, dst=0x85CD07Ea01423b1E937929B44E4Ad8c40BbB5E71, wad=99947861197947667672 ) => ( True )
  • 0xad27827c312cd5e71311d68e180a9872d42de23d.1cff79cd( )
    • 0x85cd07ea01423b1e937929b44e4ad8c40bbb5e71.ee623204( )
      • Dai.balanceOf( 0xAD27827C312Cd5E71311d68e180a9872d42dE23D ) => ( 0 )
      • WBTC.balanceOf( _owner=0x85CD07Ea01423b1E937929B44E4Ad8c40BbB5E71 ) => ( 1 )
      • Dai.balanceOf( 0x85CD07Ea01423b1E937929B44E4Ad8c40BbB5E71 ) => ( 99947861197947667673 )
      • Uniswap V3: WBTC-DAI.128acb08( )
        • WBTC.transfer( _to=0x85CD07Ea01423b1E937929B44E4Ad8c40BbB5E71, _value=125468 ) => ( True )
        • Dai.balanceOf( 0x391E8501b626C623d39474AfcA6f9e46c2686649 ) => ( 133101817650716963984736 )
        • 0x85cd07ea01423b1e937929b44e4ad8c40bbb5e71.fa461e33( )
          • Dai.transfer( dst=0x391E8501b626C623d39474AfcA6f9e46c2686649, wad=99947861197947667672 ) => ( True )
          • Dai.balanceOf( 0x391E8501b626C623d39474AfcA6f9e46c2686649 ) => ( 133201765511914911652408 )
          • Dai.balanceOf( 0xAD27827C312Cd5E71311d68e180a9872d42dE23D ) => ( 0 )
          • WBTC.balanceOf( _owner=0x85CD07Ea01423b1E937929B44E4Ad8c40BbB5E71 ) => ( 125469 )
          • WBTC.transfer( _to=0xca226bd9c754F1283123d32B2a7cF62a722f8ADa, _value=312 ) => ( True )
          • WBTC.transfer( _to=0xe5C2d742D87643031BEc4A171f92C5341a59bAA4, _value=125156 ) => ( True )
          • WBTC.balanceOf( _owner=0xe5C2d742D87643031BEc4A171f92C5341a59bAA4 ) => ( 233705 )
            File 1 of 4: RedSnwapper
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
             * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
             *
             * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
             * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
             * need to send a transaction, and thus is not required to hold Ether at all.
             */
            interface IERC20Permit {
                /**
                 * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
                 * given ``owner``'s signed approval.
                 *
                 * IMPORTANT: The same issues {IERC20-approve} has related to transaction
                 * ordering also apply here.
                 *
                 * Emits an {Approval} event.
                 *
                 * Requirements:
                 *
                 * - `spender` cannot be the zero address.
                 * - `deadline` must be a timestamp in the future.
                 * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
                 * over the EIP712-formatted function arguments.
                 * - the signature must use ``owner``'s current nonce (see {nonces}).
                 *
                 * For more information on the signature format, see the
                 * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
                 * section].
                 */
                function permit(
                    address owner,
                    address spender,
                    uint256 value,
                    uint256 deadline,
                    uint8 v,
                    bytes32 r,
                    bytes32 s
                ) external;
                /**
                 * @dev Returns the current nonce for `owner`. This value must be
                 * included whenever a signature is generated for {permit}.
                 *
                 * Every successful call to {permit} increases ``owner``'s nonce by one. This
                 * prevents a signature from being used multiple times.
                 */
                function nonces(address owner) external view returns (uint256);
                /**
                 * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
                 */
                // solhint-disable-next-line func-name-mixedcase
                function DOMAIN_SEPARATOR() external view returns (bytes32);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
            pragma solidity ^0.8.0;
            /**
             * @dev Interface of the ERC20 standard as defined in the EIP.
             */
            interface IERC20 {
                /**
                 * @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 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 `to`.
                 *
                 * Returns a boolean value indicating whether the operation succeeded.
                 *
                 * Emits a {Transfer} event.
                 */
                function transfer(address to, 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 `from` to `to` 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 from,
                    address to,
                    uint256 amount
                ) external returns (bool);
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)
            pragma solidity ^0.8.0;
            import "../IERC20.sol";
            import "../extensions/draft-IERC20Permit.sol";
            import "../../../utils/Address.sol";
            /**
             * @title SafeERC20
             * @dev Wrappers around ERC20 operations that throw on failure (when the token
             * contract returns false). Tokens that return no value (and instead revert or
             * throw on failure) are also supported, non-reverting calls are assumed to be
             * successful.
             * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
             * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
             */
            library SafeERC20 {
                using Address for address;
                function safeTransfer(
                    IERC20 token,
                    address to,
                    uint256 value
                ) internal {
                    _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
                }
                function safeTransferFrom(
                    IERC20 token,
                    address from,
                    address to,
                    uint256 value
                ) internal {
                    _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
                }
                /**
                 * @dev Deprecated. This function has issues similar to the ones found in
                 * {IERC20-approve}, and its usage is discouraged.
                 *
                 * Whenever possible, use {safeIncreaseAllowance} and
                 * {safeDecreaseAllowance} instead.
                 */
                function safeApprove(
                    IERC20 token,
                    address spender,
                    uint256 value
                ) internal {
                    // safeApprove should only be called when setting an initial allowance,
                    // or when resetting it to zero. To increase and decrease it, use
                    // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
                    require(
                        (value == 0) || (token.allowance(address(this), spender) == 0),
                        "SafeERC20: approve from non-zero to non-zero allowance"
                    );
                    _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
                }
                function safeIncreaseAllowance(
                    IERC20 token,
                    address spender,
                    uint256 value
                ) internal {
                    uint256 newAllowance = token.allowance(address(this), spender) + value;
                    _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
                }
                function safeDecreaseAllowance(
                    IERC20 token,
                    address spender,
                    uint256 value
                ) internal {
                    unchecked {
                        uint256 oldAllowance = token.allowance(address(this), spender);
                        require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
                        uint256 newAllowance = oldAllowance - value;
                        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
                    }
                }
                function safePermit(
                    IERC20Permit token,
                    address owner,
                    address spender,
                    uint256 value,
                    uint256 deadline,
                    uint8 v,
                    bytes32 r,
                    bytes32 s
                ) internal {
                    uint256 nonceBefore = token.nonces(owner);
                    token.permit(owner, spender, value, deadline, v, r, s);
                    uint256 nonceAfter = token.nonces(owner);
                    require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
                }
                /**
                 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
                 * on the return value: the return value is optional (but if data is returned, it must not be false).
                 * @param token The token targeted by the call.
                 * @param data The call data (encoded using abi.encode or one of its variants).
                 */
                function _callOptionalReturn(IERC20 token, bytes memory data) private {
                    // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
                    // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
                    // the target address contains contract code and also asserts for success in the low-level call.
                    bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
                    if (returndata.length > 0) {
                        // Return data is optional
                        require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
                    }
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
            pragma solidity ^0.8.1;
            /**
             * @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
                 * ====
                 *
                 * [IMPORTANT]
                 * ====
                 * You shouldn't rely on `isContract` to protect against flash loan attacks!
                 *
                 * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
                 * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
                 * constructor.
                 * ====
                 */
                function isContract(address account) internal view returns (bool) {
                    // This method relies on extcodesize/address.code.length, which returns 0
                    // for contracts in construction, since the code is only stored at the end
                    // of the constructor execution.
                    return account.code.length > 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");
                    (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 functionCallWithValue(target, data, 0, "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");
                    (bool success, bytes memory returndata) = target.call{value: value}(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                    return functionStaticCall(target, data, "Address: low-level static call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a static call.
                 *
                 * _Available since v3.3._
                 */
                function functionStaticCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    (bool success, bytes memory returndata) = target.staticcall(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                    return functionDelegateCall(target, data, "Address: low-level delegate call failed");
                }
                /**
                 * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                 * but performing a delegate call.
                 *
                 * _Available since v3.4._
                 */
                function functionDelegateCall(
                    address target,
                    bytes memory data,
                    string memory errorMessage
                ) internal returns (bytes memory) {
                    (bool success, bytes memory returndata) = target.delegatecall(data);
                    return verifyCallResultFromTarget(target, success, returndata, errorMessage);
                }
                /**
                 * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
                 * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
                 *
                 * _Available since v4.8._
                 */
                function verifyCallResultFromTarget(
                    address target,
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal view returns (bytes memory) {
                    if (success) {
                        if (returndata.length == 0) {
                            // only check isContract if the call was successful and the return data is empty
                            // otherwise we already know that it was a contract
                            require(isContract(target), "Address: call to non-contract");
                        }
                        return returndata;
                    } else {
                        _revert(returndata, errorMessage);
                    }
                }
                /**
                 * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
                 * revert reason or using the provided one.
                 *
                 * _Available since v4.3._
                 */
                function verifyCallResult(
                    bool success,
                    bytes memory returndata,
                    string memory errorMessage
                ) internal pure returns (bytes memory) {
                    if (success) {
                        return returndata;
                    } else {
                        _revert(returndata, errorMessage);
                    }
                }
                function _revert(bytes memory returndata, string memory errorMessage) private pure {
                    // 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
                        /// @solidity memory-safe-assembly
                        assembly {
                            let returndata_size := mload(returndata)
                            revert(add(32, returndata), returndata_size)
                        }
                    } else {
                        revert(errorMessage);
                    }
                }
            }
            // SPDX-License-Identifier: UNLICENSED
            pragma solidity 0.8.24;
            import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
            contract RedSnwapper {
              using SafeERC20 for IERC20;
              using Utils for IERC20;
              SafeExecutor public immutable safeExecutor;
              constructor() {
                safeExecutor = new SafeExecutor();
              }
              // @notice Swaps tokens
              // @notice 1. Transfers amountIn of tokens tokenIn to executor
              // @notice 2. launches executor with executorData and value = msg.value
              // @notice 3. Checks that recipient's tokenOut balance was increased at least amountOutMin
              function snwap(
                IERC20 tokenIn,
                uint amountIn, // if amountIn == 0 then amountIn = tokenIn.balance(this) - 1
                address recipient,
                IERC20 tokenOut,
                uint amountOutMin,
                address executor,
                bytes calldata executorData
              ) external payable returns (uint amountOut) {
                uint initialOutputBalance = tokenOut.universalBalanceOf(recipient);
                if (address(tokenIn) != NATIVE_ADDRESS) {
                  if (amountIn > 0) tokenIn.safeTransferFrom(msg.sender, executor, amountIn);
                  else tokenIn.safeTransfer(executor, tokenIn.balanceOf(address(this)) - 1); // -1 is slot undrain protection
                }
                safeExecutor.execute{value: msg.value}(executor, executorData);
                amountOut = tokenOut.universalBalanceOf(recipient) - initialOutputBalance;
                if (amountOut < amountOutMin)
                  revert MinimalOutputBalanceViolation(address(tokenOut), amountOut);
              }
              // @notice Swaps multiple tokens
              // @notice 1. Transfers inputTokens to inputTokens[i].transferTo
              // @notice 2. launches executors
              // @notice 3. Checks that recipient's tokenOut balance was increased at least amountOutMin
              function snwapMultiple(
                InputToken[] calldata inputTokens,
                OutputToken[] calldata outputTokens,
                Executor[] calldata executors
              ) external payable returns (uint[] memory amountOut) {
                uint[] memory initialOutputBalance = new uint[](outputTokens.length);
                for (uint i = 0; i < outputTokens.length; i++) {
                  initialOutputBalance[i] = outputTokens[i].token.universalBalanceOf(outputTokens[i].recipient);
                }
                for (uint i = 0; i < inputTokens.length; i++) {
                  IERC20 tokenIn = inputTokens[i].token;
                  if (address(tokenIn) != NATIVE_ADDRESS) {
                    if (inputTokens[i].amountIn > 0) 
                      tokenIn.safeTransferFrom(msg.sender, inputTokens[i].transferTo, inputTokens[i].amountIn);
                    else tokenIn.safeTransfer(inputTokens[i].transferTo, tokenIn.balanceOf(address(this)) - 1); // -1 is slot undrain protection
                  }
                }
                safeExecutor.executeMultiple{value: msg.value}(executors);
                amountOut = new uint[](outputTokens.length);
                for (uint i = 0; i < outputTokens.length; i++) {
                  amountOut[i] = outputTokens[i].token.universalBalanceOf(outputTokens[i].recipient) - initialOutputBalance[i];
                  if (amountOut[i] < outputTokens[i].amountOutMin)
                    revert MinimalOutputBalanceViolation(address(outputTokens[i].token), amountOut[i]);
                }
              }
            }
            // This contract doesn't have token approves, so can safely call other contracts
            contract SafeExecutor {  
              using Utils for address;
              function execute(address executor, bytes calldata executorData) external payable {
                executor.callRevertBubbleUp(msg.value, executorData);
              }
              function executeMultiple(Executor[] calldata executors) external payable {
                for (uint i = 0; i < executors.length; i++) {
                  executors[i].executor.callRevertBubbleUp(executors[i].value, executors[i].data);
                }
              }
            }
            error MinimalOutputBalanceViolation(address tokenOut, uint256 amountOut);
            address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
            struct InputToken {
              IERC20 token;
              uint amountIn;
              address transferTo;
            }
            struct OutputToken {
              IERC20 token;
              address recipient;
              uint amountOutMin;
            }
            struct Executor {
              address executor;
              uint value;
              bytes data;
            }
            library Utils {
              using SafeERC20 for IERC20;
              
              function universalBalanceOf(IERC20 token, address user) internal view returns (uint256) {
                if (address(token) == NATIVE_ADDRESS) return address(user).balance;
                else return token.balanceOf(user);
              }
              function callRevertBubbleUp(address contr, uint256 value, bytes memory data) internal {
                (bool success, bytes memory returnBytes) = contr.call{value: value}(data);
                if (!success) {
                  assembly {
                    revert(add(32, returnBytes), mload(returnBytes))
                  }
                }
              }
            }

            File 2 of 4: Dai
            // hevm: flattened sources of /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/dai.sol
            pragma solidity =0.5.12;
            
            ////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/lib.sol
            // This program is free software: you can redistribute it and/or modify
            // it under the terms of the GNU General Public License as published by
            // the Free Software Foundation, either version 3 of the License, or
            // (at your option) any later version.
            
            // This program is distributed in the hope that it will be useful,
            // but WITHOUT ANY WARRANTY; without even the implied warranty of
            // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
            // GNU General Public License for more details.
            
            // You should have received a copy of the GNU General Public License
            // along with this program.  If not, see <http://www.gnu.org/licenses/>.
            
            /* pragma solidity 0.5.12; */
            
            contract LibNote {
                event LogNote(
                    bytes4   indexed  sig,
                    address  indexed  usr,
                    bytes32  indexed  arg1,
                    bytes32  indexed  arg2,
                    bytes             data
                ) anonymous;
            
                modifier note {
                    _;
                    assembly {
                        // log an 'anonymous' event with a constant 6 words of calldata
                        // and four indexed topics: selector, caller, arg1 and arg2
                        let mark := msize                         // end of memory ensures zero
                        mstore(0x40, add(mark, 288))              // update free memory pointer
                        mstore(mark, 0x20)                        // bytes type data offset
                        mstore(add(mark, 0x20), 224)              // bytes size (padded)
                        calldatacopy(add(mark, 0x40), 0, 224)     // bytes payload
                        log4(mark, 288,                           // calldata
                             shl(224, shr(224, calldataload(0))), // msg.sig
                             caller,                              // msg.sender
                             calldataload(4),                     // arg1
                             calldataload(36)                     // arg2
                            )
                    }
                }
            }
            
            ////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/dai.sol
            // Copyright (C) 2017, 2018, 2019 dbrock, rain, mrchico
            
            // This program is free software: you can redistribute it and/or modify
            // it under the terms of the GNU Affero General Public License as published by
            // the Free Software Foundation, either version 3 of the License, or
            // (at your option) any later version.
            //
            // This program is distributed in the hope that it will be useful,
            // but WITHOUT ANY WARRANTY; without even the implied warranty of
            // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
            // GNU Affero General Public License for more details.
            //
            // You should have received a copy of the GNU Affero General Public License
            // along with this program.  If not, see <https://www.gnu.org/licenses/>.
            
            /* pragma solidity 0.5.12; */
            
            /* import "./lib.sol"; */
            
            contract Dai is LibNote {
                // --- Auth ---
                mapping (address => uint) public wards;
                function rely(address guy) external note auth { wards[guy] = 1; }
                function deny(address guy) external note auth { wards[guy] = 0; }
                modifier auth {
                    require(wards[msg.sender] == 1, "Dai/not-authorized");
                    _;
                }
            
                // --- ERC20 Data ---
                string  public constant name     = "Dai Stablecoin";
                string  public constant symbol   = "DAI";
                string  public constant version  = "1";
                uint8   public constant decimals = 18;
                uint256 public totalSupply;
            
                mapping (address => uint)                      public balanceOf;
                mapping (address => mapping (address => uint)) public allowance;
                mapping (address => uint)                      public nonces;
            
                event Approval(address indexed src, address indexed guy, uint wad);
                event Transfer(address indexed src, address indexed dst, uint wad);
            
                // --- Math ---
                function add(uint x, uint y) internal pure returns (uint z) {
                    require((z = x + y) >= x);
                }
                function sub(uint x, uint y) internal pure returns (uint z) {
                    require((z = x - y) <= x);
                }
            
                // --- EIP712 niceties ---
                bytes32 public DOMAIN_SEPARATOR;
                // bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)");
                bytes32 public constant PERMIT_TYPEHASH = 0xea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb;
            
                constructor(uint256 chainId_) public {
                    wards[msg.sender] = 1;
                    DOMAIN_SEPARATOR = keccak256(abi.encode(
                        keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                        keccak256(bytes(name)),
                        keccak256(bytes(version)),
                        chainId_,
                        address(this)
                    ));
                }
            
                // --- Token ---
                function transfer(address dst, uint wad) external returns (bool) {
                    return transferFrom(msg.sender, dst, wad);
                }
                function transferFrom(address src, address dst, uint wad)
                    public returns (bool)
                {
                    require(balanceOf[src] >= wad, "Dai/insufficient-balance");
                    if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) {
                        require(allowance[src][msg.sender] >= wad, "Dai/insufficient-allowance");
                        allowance[src][msg.sender] = sub(allowance[src][msg.sender], wad);
                    }
                    balanceOf[src] = sub(balanceOf[src], wad);
                    balanceOf[dst] = add(balanceOf[dst], wad);
                    emit Transfer(src, dst, wad);
                    return true;
                }
                function mint(address usr, uint wad) external auth {
                    balanceOf[usr] = add(balanceOf[usr], wad);
                    totalSupply    = add(totalSupply, wad);
                    emit Transfer(address(0), usr, wad);
                }
                function burn(address usr, uint wad) external {
                    require(balanceOf[usr] >= wad, "Dai/insufficient-balance");
                    if (usr != msg.sender && allowance[usr][msg.sender] != uint(-1)) {
                        require(allowance[usr][msg.sender] >= wad, "Dai/insufficient-allowance");
                        allowance[usr][msg.sender] = sub(allowance[usr][msg.sender], wad);
                    }
                    balanceOf[usr] = sub(balanceOf[usr], wad);
                    totalSupply    = sub(totalSupply, wad);
                    emit Transfer(usr, address(0), wad);
                }
                function approve(address usr, uint wad) external returns (bool) {
                    allowance[msg.sender][usr] = wad;
                    emit Approval(msg.sender, usr, wad);
                    return true;
                }
            
                // --- Alias ---
                function push(address usr, uint wad) external {
                    transferFrom(msg.sender, usr, wad);
                }
                function pull(address usr, uint wad) external {
                    transferFrom(usr, msg.sender, wad);
                }
                function move(address src, address dst, uint wad) external {
                    transferFrom(src, dst, wad);
                }
            
                // --- Approve by signature ---
                function permit(address holder, address spender, uint256 nonce, uint256 expiry,
                                bool allowed, uint8 v, bytes32 r, bytes32 s) external
                {
                    bytes32 digest =
                        keccak256(abi.encodePacked(
                            "\x19\x01",
                            DOMAIN_SEPARATOR,
                            keccak256(abi.encode(PERMIT_TYPEHASH,
                                                 holder,
                                                 spender,
                                                 nonce,
                                                 expiry,
                                                 allowed))
                    ));
            
                    require(holder != address(0), "Dai/invalid-address-0");
                    require(holder == ecrecover(digest, v, r, s), "Dai/invalid-permit");
                    require(expiry == 0 || now <= expiry, "Dai/permit-expired");
                    require(nonce == nonces[holder]++, "Dai/invalid-nonce");
                    uint wad = allowed ? uint(-1) : 0;
                    allowance[holder][spender] = wad;
                    emit Approval(holder, spender, wad);
                }
            }

            File 3 of 4: WBTC
            pragma solidity 0.4.24;
            
            // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol
            
            /**
             * @title ERC20Basic
             * @dev Simpler version of ERC20 interface
             * See https://github.com/ethereum/EIPs/issues/179
             */
            contract ERC20Basic {
              function totalSupply() public view returns (uint256);
              function balanceOf(address _who) public view returns (uint256);
              function transfer(address _to, uint256 _value) public returns (bool);
              event Transfer(address indexed from, address indexed to, uint256 value);
            }
            
            // File: openzeppelin-solidity/contracts/math/SafeMath.sol
            
            /**
             * @title SafeMath
             * @dev Math operations with safety checks that throw on error
             */
            library SafeMath {
            
              /**
              * @dev Multiplies two numbers, throws on overflow.
              */
              function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
                // benefit is lost if 'b' is also tested.
                // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                if (_a == 0) {
                  return 0;
                }
            
                c = _a * _b;
                assert(c / _a == _b);
                return c;
              }
            
              /**
              * @dev Integer division of two numbers, truncating the quotient.
              */
              function div(uint256 _a, uint256 _b) internal pure returns (uint256) {
                // assert(_b > 0); // Solidity automatically throws when dividing by 0
                // uint256 c = _a / _b;
                // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold
                return _a / _b;
              }
            
              /**
              * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
              */
              function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
                assert(_b <= _a);
                return _a - _b;
              }
            
              /**
              * @dev Adds two numbers, throws on overflow.
              */
              function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                c = _a + _b;
                assert(c >= _a);
                return c;
              }
            }
            
            // File: openzeppelin-solidity/contracts/token/ERC20/BasicToken.sol
            
            /**
             * @title Basic token
             * @dev Basic version of StandardToken, with no allowances.
             */
            contract BasicToken is ERC20Basic {
              using SafeMath for uint256;
            
              mapping(address => uint256) internal balances;
            
              uint256 internal totalSupply_;
            
              /**
              * @dev Total number of tokens in existence
              */
              function totalSupply() public view returns (uint256) {
                return totalSupply_;
              }
            
              /**
              * @dev Transfer token for a specified address
              * @param _to The address to transfer to.
              * @param _value The amount to be transferred.
              */
              function transfer(address _to, uint256 _value) public returns (bool) {
                require(_value <= balances[msg.sender]);
                require(_to != address(0));
            
                balances[msg.sender] = balances[msg.sender].sub(_value);
                balances[_to] = balances[_to].add(_value);
                emit Transfer(msg.sender, _to, _value);
                return true;
              }
            
              /**
              * @dev Gets the balance of the specified address.
              * @param _owner The address to query the the balance of.
              * @return An uint256 representing the amount owned by the passed address.
              */
              function balanceOf(address _owner) public view returns (uint256) {
                return balances[_owner];
              }
            
            }
            
            // File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol
            
            /**
             * @title ERC20 interface
             * @dev see https://github.com/ethereum/EIPs/issues/20
             */
            contract ERC20 is ERC20Basic {
              function allowance(address _owner, address _spender)
                public view returns (uint256);
            
              function transferFrom(address _from, address _to, uint256 _value)
                public returns (bool);
            
              function approve(address _spender, uint256 _value) public returns (bool);
              event Approval(
                address indexed owner,
                address indexed spender,
                uint256 value
              );
            }
            
            // File: openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol
            
            /**
             * @title Standard ERC20 token
             *
             * @dev Implementation of the basic standard token.
             * https://github.com/ethereum/EIPs/issues/20
             * Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
             */
            contract StandardToken is ERC20, BasicToken {
            
              mapping (address => mapping (address => uint256)) internal allowed;
            
            
              /**
               * @dev Transfer tokens from one address to another
               * @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 amount of tokens to be transferred
               */
              function transferFrom(
                address _from,
                address _to,
                uint256 _value
              )
                public
                returns (bool)
              {
                require(_value <= balances[_from]);
                require(_value <= allowed[_from][msg.sender]);
                require(_to != address(0));
            
                balances[_from] = balances[_from].sub(_value);
                balances[_to] = balances[_to].add(_value);
                allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
                emit Transfer(_from, _to, _value);
                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 _spender The address which will spend the funds.
               * @param _value The amount of tokens to be spent.
               */
              function approve(address _spender, uint256 _value) public returns (bool) {
                allowed[msg.sender][_spender] = _value;
                emit Approval(msg.sender, _spender, _value);
                return true;
              }
            
              /**
               * @dev Function to check the amount of tokens that an owner allowed to a spender.
               * @param _owner address The address which owns the funds.
               * @param _spender address The address which will spend the funds.
               * @return A uint256 specifying the amount of tokens still available for the spender.
               */
              function allowance(
                address _owner,
                address _spender
               )
                public
                view
                returns (uint256)
              {
                return allowed[_owner][_spender];
              }
            
              /**
               * @dev Increase the amount of tokens that an owner allowed to a spender.
               * approve should be called when allowed[_spender] == 0. To increment
               * allowed value is better to use this function to avoid 2 calls (and wait until
               * the first transaction is mined)
               * From MonolithDAO Token.sol
               * @param _spender The address which will spend the funds.
               * @param _addedValue The amount of tokens to increase the allowance by.
               */
              function increaseApproval(
                address _spender,
                uint256 _addedValue
              )
                public
                returns (bool)
              {
                allowed[msg.sender][_spender] = (
                  allowed[msg.sender][_spender].add(_addedValue));
                emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
                return true;
              }
            
              /**
               * @dev Decrease the amount of tokens that an owner allowed to a spender.
               * approve should be called when allowed[_spender] == 0. To decrement
               * allowed value is better to use this function to avoid 2 calls (and wait until
               * the first transaction is mined)
               * From MonolithDAO Token.sol
               * @param _spender The address which will spend the funds.
               * @param _subtractedValue The amount of tokens to decrease the allowance by.
               */
              function decreaseApproval(
                address _spender,
                uint256 _subtractedValue
              )
                public
                returns (bool)
              {
                uint256 oldValue = allowed[msg.sender][_spender];
                if (_subtractedValue >= oldValue) {
                  allowed[msg.sender][_spender] = 0;
                } else {
                  allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
                }
                emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
                return true;
              }
            
            }
            
            // File: openzeppelin-solidity/contracts/token/ERC20/DetailedERC20.sol
            
            /**
             * @title DetailedERC20 token
             * @dev The decimals are only for visualization purposes.
             * All the operations are done using the smallest and indivisible token unit,
             * just as on Ethereum all the operations are done in wei.
             */
            contract DetailedERC20 is ERC20 {
              string public name;
              string public symbol;
              uint8 public decimals;
            
              constructor(string _name, string _symbol, uint8 _decimals) public {
                name = _name;
                symbol = _symbol;
                decimals = _decimals;
              }
            }
            
            // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
            
            /**
             * @title Ownable
             * @dev The Ownable contract has an owner address, and provides basic authorization control
             * functions, this simplifies the implementation of "user permissions".
             */
            contract Ownable {
              address public owner;
            
            
              event OwnershipRenounced(address indexed previousOwner);
              event OwnershipTransferred(
                address indexed previousOwner,
                address indexed newOwner
              );
            
            
              /**
               * @dev The Ownable constructor sets the original `owner` of the contract to the sender
               * account.
               */
              constructor() public {
                owner = msg.sender;
              }
            
              /**
               * @dev Throws if called by any account other than the owner.
               */
              modifier onlyOwner() {
                require(msg.sender == owner);
                _;
              }
            
              /**
               * @dev Allows the current owner to relinquish control of the contract.
               * @notice Renouncing to ownership will leave the contract without an owner.
               * It will not be possible to call the functions with the `onlyOwner`
               * modifier anymore.
               */
              function renounceOwnership() public onlyOwner {
                emit OwnershipRenounced(owner);
                owner = address(0);
              }
            
              /**
               * @dev Allows the current owner to transfer control of the contract to a newOwner.
               * @param _newOwner The address to transfer ownership to.
               */
              function transferOwnership(address _newOwner) public onlyOwner {
                _transferOwnership(_newOwner);
              }
            
              /**
               * @dev Transfers control of the contract to a newOwner.
               * @param _newOwner The address to transfer ownership to.
               */
              function _transferOwnership(address _newOwner) internal {
                require(_newOwner != address(0));
                emit OwnershipTransferred(owner, _newOwner);
                owner = _newOwner;
              }
            }
            
            // File: openzeppelin-solidity/contracts/token/ERC20/MintableToken.sol
            
            /**
             * @title Mintable token
             * @dev Simple ERC20 Token example, with mintable token creation
             * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
             */
            contract MintableToken is StandardToken, Ownable {
              event Mint(address indexed to, uint256 amount);
              event MintFinished();
            
              bool public mintingFinished = false;
            
            
              modifier canMint() {
                require(!mintingFinished);
                _;
              }
            
              modifier hasMintPermission() {
                require(msg.sender == owner);
                _;
              }
            
              /**
               * @dev Function to mint tokens
               * @param _to The address that will receive the minted tokens.
               * @param _amount The amount of tokens to mint.
               * @return A boolean that indicates if the operation was successful.
               */
              function mint(
                address _to,
                uint256 _amount
              )
                public
                hasMintPermission
                canMint
                returns (bool)
              {
                totalSupply_ = totalSupply_.add(_amount);
                balances[_to] = balances[_to].add(_amount);
                emit Mint(_to, _amount);
                emit Transfer(address(0), _to, _amount);
                return true;
              }
            
              /**
               * @dev Function to stop minting new tokens.
               * @return True if the operation was successful.
               */
              function finishMinting() public onlyOwner canMint returns (bool) {
                mintingFinished = true;
                emit MintFinished();
                return true;
              }
            }
            
            // File: openzeppelin-solidity/contracts/token/ERC20/BurnableToken.sol
            
            /**
             * @title Burnable Token
             * @dev Token that can be irreversibly burned (destroyed).
             */
            contract BurnableToken is BasicToken {
            
              event Burn(address indexed burner, uint256 value);
            
              /**
               * @dev Burns a specific amount of tokens.
               * @param _value The amount of token to be burned.
               */
              function burn(uint256 _value) public {
                _burn(msg.sender, _value);
              }
            
              function _burn(address _who, uint256 _value) internal {
                require(_value <= balances[_who]);
                // no need to require value <= totalSupply, since that would imply the
                // sender's balance is greater than the totalSupply, which *should* be an assertion failure
            
                balances[_who] = balances[_who].sub(_value);
                totalSupply_ = totalSupply_.sub(_value);
                emit Burn(_who, _value);
                emit Transfer(_who, address(0), _value);
              }
            }
            
            // File: openzeppelin-solidity/contracts/lifecycle/Pausable.sol
            
            /**
             * @title Pausable
             * @dev Base contract which allows children to implement an emergency stop mechanism.
             */
            contract Pausable is Ownable {
              event Pause();
              event Unpause();
            
              bool public paused = false;
            
            
              /**
               * @dev Modifier to make a function callable only when the contract is not paused.
               */
              modifier whenNotPaused() {
                require(!paused);
                _;
              }
            
              /**
               * @dev Modifier to make a function callable only when the contract is paused.
               */
              modifier whenPaused() {
                require(paused);
                _;
              }
            
              /**
               * @dev called by the owner to pause, triggers stopped state
               */
              function pause() public onlyOwner whenNotPaused {
                paused = true;
                emit Pause();
              }
            
              /**
               * @dev called by the owner to unpause, returns to normal state
               */
              function unpause() public onlyOwner whenPaused {
                paused = false;
                emit Unpause();
              }
            }
            
            // File: openzeppelin-solidity/contracts/token/ERC20/PausableToken.sol
            
            /**
             * @title Pausable token
             * @dev StandardToken modified with pausable transfers.
             **/
            contract PausableToken is StandardToken, Pausable {
            
              function transfer(
                address _to,
                uint256 _value
              )
                public
                whenNotPaused
                returns (bool)
              {
                return super.transfer(_to, _value);
              }
            
              function transferFrom(
                address _from,
                address _to,
                uint256 _value
              )
                public
                whenNotPaused
                returns (bool)
              {
                return super.transferFrom(_from, _to, _value);
              }
            
              function approve(
                address _spender,
                uint256 _value
              )
                public
                whenNotPaused
                returns (bool)
              {
                return super.approve(_spender, _value);
              }
            
              function increaseApproval(
                address _spender,
                uint _addedValue
              )
                public
                whenNotPaused
                returns (bool success)
              {
                return super.increaseApproval(_spender, _addedValue);
              }
            
              function decreaseApproval(
                address _spender,
                uint _subtractedValue
              )
                public
                whenNotPaused
                returns (bool success)
              {
                return super.decreaseApproval(_spender, _subtractedValue);
              }
            }
            
            // File: openzeppelin-solidity/contracts/ownership/Claimable.sol
            
            /**
             * @title Claimable
             * @dev Extension for the Ownable contract, where the ownership needs to be claimed.
             * This allows the new owner to accept the transfer.
             */
            contract Claimable is Ownable {
              address public pendingOwner;
            
              /**
               * @dev Modifier throws if called by any account other than the pendingOwner.
               */
              modifier onlyPendingOwner() {
                require(msg.sender == pendingOwner);
                _;
              }
            
              /**
               * @dev Allows the current owner to set the pendingOwner address.
               * @param newOwner The address to transfer ownership to.
               */
              function transferOwnership(address newOwner) public onlyOwner {
                pendingOwner = newOwner;
              }
            
              /**
               * @dev Allows the pendingOwner address to finalize the transfer.
               */
              function claimOwnership() public onlyPendingOwner {
                emit OwnershipTransferred(owner, pendingOwner);
                owner = pendingOwner;
                pendingOwner = address(0);
              }
            }
            
            // File: openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol
            
            /**
             * @title SafeERC20
             * @dev Wrappers around ERC20 operations that throw on failure.
             * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
             * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
             */
            library SafeERC20 {
              function safeTransfer(
                ERC20Basic _token,
                address _to,
                uint256 _value
              )
                internal
              {
                require(_token.transfer(_to, _value));
              }
            
              function safeTransferFrom(
                ERC20 _token,
                address _from,
                address _to,
                uint256 _value
              )
                internal
              {
                require(_token.transferFrom(_from, _to, _value));
              }
            
              function safeApprove(
                ERC20 _token,
                address _spender,
                uint256 _value
              )
                internal
              {
                require(_token.approve(_spender, _value));
              }
            }
            
            // File: openzeppelin-solidity/contracts/ownership/CanReclaimToken.sol
            
            /**
             * @title Contracts that should be able to recover tokens
             * @author SylTi
             * @dev This allow a contract to recover any ERC20 token received in a contract by transferring the balance to the contract owner.
             * This will prevent any accidental loss of tokens.
             */
            contract CanReclaimToken is Ownable {
              using SafeERC20 for ERC20Basic;
            
              /**
               * @dev Reclaim all ERC20Basic compatible tokens
               * @param _token ERC20Basic The address of the token contract
               */
              function reclaimToken(ERC20Basic _token) external onlyOwner {
                uint256 balance = _token.balanceOf(this);
                _token.safeTransfer(owner, balance);
              }
            
            }
            
            // File: contracts/utils/OwnableContract.sol
            
            // empty block is used as this contract just inherits others.
            contract OwnableContract is CanReclaimToken, Claimable { } /* solhint-disable-line no-empty-blocks */
            
            // File: contracts/token/WBTC.sol
            
            contract WBTC is StandardToken, DetailedERC20("Wrapped BTC", "WBTC", 8),
                MintableToken, BurnableToken, PausableToken, OwnableContract {
            
                function burn(uint value) public onlyOwner {
                    super.burn(value);
                }
            
                function finishMinting() public onlyOwner returns (bool) {
                    return false;
                }
            
                function renounceOwnership() public onlyOwner {
                    revert("renouncing ownership is blocked");
                }
            }

            File 4 of 4: TokenChomper
            // SPDX-License-Identifier: GPL-3.0-or-later
            pragma solidity >=0.8.0;
            import "/interfaces/IRouteProcessor.sol";
            import "interfaces/IERC20.sol";
            import "./Auth.sol";
            /// @title TokenChomper for selling accumulated tokens for weth or other base assets
            /// @notice This contract will be used for fee collection and breakdown
            /// @dev Uses Auth contract for 2-step owner process and trust operators to guard functions
            contract TokenChomper is Auth {
              address public immutable weth;
              IRouteProcessor public routeProcessor;
              bytes4 private constant TRANSFER_SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)')));
              error TransferFailed();
              constructor(
                address _operator,
                address _routeProcessor,
                address _weth
              ) Auth(_operator) {
                // initial owner is msg.sender
                routeProcessor = IRouteProcessor(_routeProcessor);
                weth = _weth;
              }
              /// @notice Updates the route processor to be used for swapping tokens
              /// @dev make sure new route processor is backwards compatiable (should be)
              /// @param _routeProcessor The address of the new route processor
              function updateRouteProcessor(address _routeProcessor) external onlyOwner {
                routeProcessor = IRouteProcessor(_routeProcessor);
              }
              
              /// @notice Processes a route selling any of the tokens in TokenChomper for an output token
              /// @dev can be called by operators
              /// @param tokenIn The address of the token to be sold
              /// @param amountIn The amount of the token to be sold
              /// @param tokenOut The address of the token to be bought
              /// @param amoutOutMin The minimum amount of the token to be bought (slippage protection)
              /// @param route The route to be used for swapping
              function processRoute(
                address tokenIn,
                uint256 amountIn,
                address tokenOut,
                uint256 amoutOutMin,
                bytes memory route
              ) external onlyTrusted {
                // process route to any output token, slippage will be handled by the route processor
                IERC20(tokenIn).transfer(address(routeProcessor), amountIn);
                routeProcessor.processRoute(
                  tokenIn, amountIn, tokenOut, amoutOutMin, address(this), route
                ); 
              }
              /// @notice Withdraw any token or eth from the contract
              /// @dev can only be called by owner
              /// @param token The address of the token to be withdrawn, 0x0 for eth
              /// @param to The address to send the token to
              /// @param _value The amount of the token to be withdrawn
              function withdraw(address token, address to, uint256 _value) onlyOwner external {
                if (token != address(0)) {
                  _safeTransfer(token, to, _value);
                } 
                else {
                  (bool success, ) = to.call{value: _value}("");
                  require(success);
                }
              }
              
              function _safeTransfer(address token, address to, uint value) internal {
                (bool success, bytes memory data) = token.call(abi.encodeWithSelector(TRANSFER_SELECTOR, to, value));
                if (!success || (data.length != 0 && !abi.decode(data, (bool)))) revert TransferFailed();
              }
              /// @notice In case we receive any unwrapped eth (native token) we can call this
              /// @dev operators can call this 
              function wrapEth() onlyTrusted external {
                weth.call{value: address(this).balance}("");
              }
              /// @notice Available function in case we need to do any calls that aren't supported by the contract (unwinding lp positions, etc.)
              /// @dev can only be called by owner
              /// @param to The address to send the call to
              /// @param _value The amount of eth to send with the call
              /// @param data The data to be sent with the call
              function doAction(address to, uint256 _value, bytes memory data) onlyOwner external {
                (bool success, ) = to.call{value: _value}(data);
                require(success);
              }
              receive() external payable {}
            }// SPDX-License-Identifier: GPL-3.0-or-later
            pragma solidity >= 0.8.0;
            interface IRouteProcessor {
              
              struct RouteProcessorData {
                    address tokenIn;
                    uint256 amountIn;
                    address tokenOut;
                    uint256 amountOutMin;
                    address to;
                    bytes route;
              }
              
              function processRoute(
                address tokenIn,
                uint256 amountIn,
                address tokenOut,
                uint256 amountOutMin,
                address to,
                bytes memory route
              ) external payable returns (uint256 amountOut);
            }// SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
            pragma solidity >= 0.8.0;
            /**
             * @dev Interface of the ERC20 standard as defined in the EIP.
             */
            interface IERC20 {
                /**
                 * @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 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 `to`.
                 *
                 * Returns a boolean value indicating whether the operation succeeded.
                 *
                 * Emits a {Transfer} event.
                 */
                function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool);
            }// SPDX-License-Identifier: GPL-3.0-or-later
            pragma solidity >=0.8.0;
            import "openzeppelin/access/Ownable2Step.sol";
            abstract contract Auth is Ownable2Step {
                event SetTrusted(address indexed user, bool isTrusted);
                mapping(address => bool) public trusted;
                error OnlyTrusted();
                modifier onlyTrusted() {
                    if (!trusted[msg.sender]) revert OnlyTrusted();
                    _;
                }
                constructor(address trustedUser) {
                    trusted[trustedUser] = true;
                    emit SetTrusted(trustedUser, true);
                }
                function setTrusted(address user, bool isTrusted) external onlyOwner {
                    trusted[user] = isTrusted;
                    emit SetTrusted(user, isTrusted);
                }
            }// SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.8.0) (access/Ownable2Step.sol)
            pragma solidity ^0.8.0;
            import "./Ownable.sol";
            /**
             * @dev Contract module which provides access control mechanism, where
             * there is an account (an owner) that can be granted exclusive access to
             * specific functions.
             *
             * By default, the owner account will be the one that deploys the contract. This
             * can later be changed with {transferOwnership} and {acceptOwnership}.
             *
             * This module is used through inheritance. It will make available all functions
             * from parent (Ownable).
             */
            abstract contract Ownable2Step is Ownable {
                address private _pendingOwner;
                event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
                /**
                 * @dev Returns the address of the pending owner.
                 */
                function pendingOwner() public view virtual returns (address) {
                    return _pendingOwner;
                }
                /**
                 * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
                 * Can only be called by the current owner.
                 */
                function transferOwnership(address newOwner) public virtual override onlyOwner {
                    _pendingOwner = newOwner;
                    emit OwnershipTransferStarted(owner(), newOwner);
                }
                /**
                 * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
                 * Internal function without access restriction.
                 */
                function _transferOwnership(address newOwner) internal virtual override {
                    delete _pendingOwner;
                    super._transferOwnership(newOwner);
                }
                /**
                 * @dev The new owner accepts the ownership transfer.
                 */
                function acceptOwnership() external {
                    address sender = _msgSender();
                    require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
                    _transferOwnership(sender);
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
            pragma solidity ^0.8.0;
            import "../utils/Context.sol";
            /**
             * @dev Contract module which provides a basic access control mechanism, where
             * there is an account (an owner) that can be granted exclusive access to
             * specific functions.
             *
             * By default, the owner account will be the one that deploys the contract. This
             * can later be changed with {transferOwnership}.
             *
             * This module is used through inheritance. It will make available the modifier
             * `onlyOwner`, which can be applied to your functions to restrict their use to
             * the owner.
             */
            abstract contract Ownable is Context {
                address private _owner;
                event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
                /**
                 * @dev Initializes the contract setting the deployer as the initial owner.
                 */
                constructor() {
                    _transferOwnership(_msgSender());
                }
                /**
                 * @dev Throws if called by any account other than the owner.
                 */
                modifier onlyOwner() {
                    _checkOwner();
                    _;
                }
                /**
                 * @dev Returns the address of the current owner.
                 */
                function owner() public view virtual returns (address) {
                    return _owner;
                }
                /**
                 * @dev Throws if the sender is not the owner.
                 */
                function _checkOwner() internal view virtual {
                    require(owner() == _msgSender(), "Ownable: caller is not the owner");
                }
                /**
                 * @dev Leaves the contract without owner. It will not be possible to call
                 * `onlyOwner` functions anymore. Can only be called by the current owner.
                 *
                 * NOTE: Renouncing ownership will leave the contract without an owner,
                 * thereby removing any functionality that is only available to the owner.
                 */
                function renounceOwnership() public virtual onlyOwner {
                    _transferOwnership(address(0));
                }
                /**
                 * @dev Transfers ownership of the contract to a new account (`newOwner`).
                 * Can only be called by the current owner.
                 */
                function transferOwnership(address newOwner) public virtual onlyOwner {
                    require(newOwner != address(0), "Ownable: new owner is the zero address");
                    _transferOwnership(newOwner);
                }
                /**
                 * @dev Transfers ownership of the contract to a new account (`newOwner`).
                 * Internal function without access restriction.
                 */
                function _transferOwnership(address newOwner) internal virtual {
                    address oldOwner = _owner;
                    _owner = newOwner;
                    emit OwnershipTransferred(oldOwner, newOwner);
                }
            }
            // SPDX-License-Identifier: MIT
            // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
            pragma solidity ^0.8.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 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) {
                    return msg.sender;
                }
                function _msgData() internal view virtual returns (bytes calldata) {
                    return msg.data;
                }
            }