ETH Price: $2,869.54 (-2.44%)

Contract

0xD6B34F97d4A8Cb38D0544dB241CB3f335866f490

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Arb34252952322026-01-26 4:11:2024 mins ago1769400680IN
0xD6B34F97...35866f490
0 ETH0.000007430.02005
Arb34252819182026-01-26 3:15:551 hr ago1769397355IN
0xD6B34F97...35866f490
0 ETH0.000007420.020032
Arb34252686822026-01-26 2:20:522 hrs ago1769394052IN
0xD6B34F97...35866f490
0 ETH0.000007410.02
Arb34252552382026-01-26 1:24:563 hrs ago1769390696IN
0xD6B34F97...35866f490
0 ETH0.000007430.02
Arb34252525902026-01-26 1:13:553 hrs ago1769390035IN
0xD6B34F97...35866f490
0 ETH0.000010370.02
Arb34252419622026-01-26 0:29:354 hrs ago1769387375IN
0xD6B34F97...35866f490
0 ETH0.000007430.02
Arb34252286622026-01-25 23:34:115 hrs ago1769384051IN
0xD6B34F97...35866f490
0 ETH0.00000750.020146
Arb34252154382026-01-25 22:39:065 hrs ago1769380746IN
0xD6B34F97...35866f490
0 ETH0.000007820.02003
Arb34252021012026-01-25 21:43:296 hrs ago1769377409IN
0xD6B34F97...35866f490
0 ETH0.000007470.020054
Arb34251887232026-01-25 20:47:397 hrs ago1769374059IN
0xD6B34F97...35866f490
0 ETH0.000007480.020006
Arb34251753492026-01-25 19:52:038 hrs ago1769370723IN
0xD6B34F97...35866f490
0 ETH0.000007620.020212
Arb34251681552026-01-25 19:22:169 hrs ago1769368936IN
0xD6B34F97...35866f490
0 ETH0.000012870.02028
Arb34251619652026-01-25 18:56:309 hrs ago1769367390IN
0xD6B34F97...35866f490
0 ETH0.000007520.020042
Arb34251486252026-01-25 18:01:0210 hrs ago1769364062IN
0xD6B34F97...35866f490
0 ETH0.00000740.02
Arb34251453442026-01-25 17:47:2110 hrs ago1769363241IN
0xD6B34F97...35866f490
0 ETH0.000010840.02
Arb34251354072026-01-25 17:05:5611 hrs ago1769360756IN
0xD6B34F97...35866f490
0 ETH0.000007490.020124
Arb34251219412026-01-25 16:10:0212 hrs ago1769357402IN
0xD6B34F97...35866f490
0 ETH0.000007440.020078
Arb34251085162026-01-25 15:14:0513 hrs ago1769354045IN
0xD6B34F97...35866f490
0 ETH0.000007410.02
Arb34250951982026-01-25 14:18:3914 hrs ago1769350719IN
0xD6B34F97...35866f490
0 ETH0.000007480.020174
Arb34250879762026-01-25 13:48:3414 hrs ago1769348914IN
0xD6B34F97...35866f490
0 ETH0.000010540.020036
Arb34250818612026-01-25 13:23:0615 hrs ago1769347386IN
0xD6B34F97...35866f490
0 ETH0.000007750.02
Arb34250685262026-01-25 12:27:3316 hrs ago1769344053IN
0xD6B34F97...35866f490
0 ETH0.000007430.02004
Arb34250550652026-01-25 11:31:3917 hrs ago1769340699IN
0xD6B34F97...35866f490
0 ETH0.000007420.02
Arb34250417762026-01-25 10:36:1817 hrs ago1769337378IN
0xD6B34F97...35866f490
0 ETH0.000007450.020086
Arb34250285112026-01-25 9:41:0018 hrs ago1769334060IN
0xD6B34F97...35866f490
0 ETH0.00000770.020774
View all transactions

Parent Transaction Hash Block From To
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
RouteProcessorOrderBookV4ArbOrderTaker

Compiler Version
v0.8.25+commit.b61c2a91

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
paris EvmVersion
File 1 of 55 : RouteProcessorOrderBookV4ArbOrderTaker.sol
// SPDX-License-Identifier: CAL
pragma solidity =0.8.25;

import {IRouteProcessor} from "sushixswap-v2/src/interfaces/IRouteProcessor.sol";
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import {Address} from "openzeppelin-contracts/contracts/utils/Address.sol";

import {OrderBookV4ArbOrderTaker, OrderBookV4ArbConfigV2} from "../../abstract/OrderBookV4ArbOrderTaker.sol";

contract RouteProcessorOrderBookV4ArbOrderTaker is OrderBookV4ArbOrderTaker {
    using SafeERC20 for IERC20;
    using Address for address;

    IRouteProcessor public immutable iRouteProcessor;

    constructor(OrderBookV4ArbConfigV2 memory config) OrderBookV4ArbOrderTaker(config) {
        (address routeProcessor) = abi.decode(config.implementationData, (address));
        iRouteProcessor = IRouteProcessor(routeProcessor);
    }

    /// @inheritdoc OrderBookV4ArbOrderTaker
    function onTakeOrders(
        address inputToken,
        address outputToken,
        uint256 inputAmountSent,
        uint256 totalOutputAmount,
        bytes calldata takeOrdersData
    ) public virtual override {
        super.onTakeOrders(inputToken, outputToken, inputAmountSent, totalOutputAmount, takeOrdersData);
        IERC20(inputToken).safeApprove(address(iRouteProcessor), 0);
        IERC20(inputToken).safeApprove(address(iRouteProcessor), type(uint256).max);
        bytes memory route = abi.decode(takeOrdersData, (bytes));
        (uint256 amountOut) = iRouteProcessor.processRoute(
            inputToken, inputAmountSent, outputToken, totalOutputAmount, address(this), route
        );
        IERC20(inputToken).safeApprove(address(iRouteProcessor), 0);
        (amountOut);
    }

    /// Allow receiving gas.
    fallback() external {}
}

File 2 of 55 : IRouteProcessor.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity >=0.8.10;

interface IRouteProcessor {
    
    struct RouteProcessorData {
        address tokenIn;
        uint256 amountIn;
        address tokenOut;
        uint256 amountOutMin;
        address to;
        bytes route;
    }
    
    /// @notice Process a swap with passed route on RouteProcessor
    /// @param tokenIn The address of the token to swap from
    /// @param amountIn The amount of token to swap from
    /// @param tokenOut The address of the token to swap to
    /// @param amountOutMin The minimum amount of token to receive
    /// @param to The address to send the swapped token to
    /// @param route The route to use for the swap
    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: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../extensions/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;

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    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));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    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");
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
     * Revert on invalid signature.
     */
    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");
        require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation 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).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // 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 cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return
            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.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
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [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://consensys.net/diligence/blog/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.8.0/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: CAL
pragma solidity ^0.8.19;

import {ERC165, IERC165} from "openzeppelin-contracts/contracts/utils/introspection/ERC165.sol";
import {ReentrancyGuard} from "openzeppelin-contracts/contracts/security/ReentrancyGuard.sol";
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import {Address} from "openzeppelin-contracts/contracts/utils/Address.sol";
import {SourceIndexV2} from "rain.interpreter.interface/interface/IInterpreterV3.sol";
import {
    EncodedDispatch,
    LibEncodedDispatch
} from "rain.interpreter.interface/lib/deprecated/caller/LibEncodedDispatch.sol";
import {LibNamespace} from "rain.interpreter.interface/lib/ns/LibNamespace.sol";
import {IOrderBookV4, NoOrders} from "rain.orderbook.interface/interface/IOrderBookV4.sol";
import {
    IOrderBookV4,
    IOrderBookV4ArbOrderTakerV2,
    IOrderBookV4OrderTaker,
    TaskV1
} from "rain.orderbook.interface/interface/unstable/IOrderBookV4ArbOrderTakerV2.sol";
import {IInterpreterV3, DEFAULT_STATE_NAMESPACE} from "rain.interpreter.interface/interface/IInterpreterV3.sol";
import {IInterpreterStoreV2} from "rain.interpreter.interface/interface/IInterpreterStoreV2.sol";
import {TakeOrdersConfigV3} from "rain.orderbook.interface/interface/IOrderBookV4.sol";
import {OrderBookV4ArbConfigV2, EvaluableV3, OrderBookV4ArbCommon, SignedContextV1} from "./OrderBookV4ArbCommon.sol";
import {LibContext} from "rain.interpreter.interface/lib/caller/LibContext.sol";
import {LibBytecode} from "rain.interpreter.interface/lib/bytecode/LibBytecode.sol";
import {LibOrderBook} from "../lib/LibOrderBook.sol";
import {LibOrderBookArb, NonZeroBeforeArbStack, BadLender} from "../lib/LibOrderBookArb.sol";

/// Thrown when "before arb" wants inputs that we don't have.
error NonZeroBeforeArbInputs(uint256 inputs);

/// @dev "Before arb" is evaluabled before the arb is executed. Ostensibly this
/// is to allow for access control to the arb, the return values are ignored.
SourceIndexV2 constant BEFORE_ARB_SOURCE_INDEX = SourceIndexV2.wrap(0);

abstract contract OrderBookV4ArbOrderTaker is
    IOrderBookV4ArbOrderTakerV2,
    ReentrancyGuard,
    ERC165,
    OrderBookV4ArbCommon
{
    using SafeERC20 for IERC20;

    constructor(OrderBookV4ArbConfigV2 memory config) OrderBookV4ArbCommon(config) {}

    /// @inheritdoc IERC165
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return (interfaceId == type(IOrderBookV4OrderTaker).interfaceId)
            || (interfaceId == type(IOrderBookV4ArbOrderTakerV2).interfaceId) || super.supportsInterface(interfaceId);
    }

    /// @inheritdoc IOrderBookV4ArbOrderTakerV2
    function arb3(IOrderBookV4 orderBook, TakeOrdersConfigV3 calldata takeOrders, TaskV1 calldata task)
        external
        payable
        nonReentrant
        onlyValidTask(task)
    {
        // Mimic what OB would do anyway if called with zero orders.
        if (takeOrders.orders.length == 0) {
            revert NoOrders();
        }

        address ordersInputToken = takeOrders.orders[0].order.validInputs[takeOrders.orders[0].inputIOIndex].token;
        address ordersOutputToken = takeOrders.orders[0].order.validOutputs[takeOrders.orders[0].outputIOIndex].token;

        IERC20(ordersInputToken).safeApprove(address(orderBook), 0);
        IERC20(ordersInputToken).safeApprove(address(orderBook), type(uint256).max);
        (uint256 totalInput, uint256 totalOutput) = orderBook.takeOrders2(takeOrders);
        (totalInput, totalOutput);
        IERC20(ordersInputToken).safeApprove(address(orderBook), 0);

        LibOrderBookArb.finalizeArb(task, ordersInputToken, ordersOutputToken);
    }

    /// @inheritdoc IOrderBookV4OrderTaker
    function onTakeOrders(address, address, uint256, uint256, bytes calldata) public virtual override {}
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/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.
 *
 * ==== Security Considerations
 *
 * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
 * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
 * considered as an intention to spend the allowance in any specific way. The second is that because permits have
 * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
 * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
 * generally recommended is:
 *
 * ```solidity
 * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
 *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
 *     doThing(..., value);
 * }
 *
 * function doThing(..., uint256 value) public {
 *     token.safeTransferFrom(msg.sender, address(this), value);
 *     ...
 * }
 * ```
 *
 * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
 * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
 * {SafeERC20-safeTransferFrom}).
 *
 * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
 * contracts should have entry points that don't rely on permit.
 */
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].
     *
     * CAUTION: See Security Considerations above.
     */
    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 v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {
    IInterpreterStoreV2,
    FullyQualifiedNamespace,
    StateNamespace,
    SourceIndexV2,
    DEFAULT_STATE_NAMESPACE,
    Operand,
    OPCODE_CONSTANT,
    OPCODE_CONTEXT,
    OPCODE_EXTERN,
    OPCODE_UNKNOWN,
    OPCODE_STACK
} from "./deprecated/IInterpreterV2.sol";

interface IInterpreterV3 {
    function functionPointers() external view returns (bytes calldata);

    function eval3(
        IInterpreterStoreV2 store,
        FullyQualifiedNamespace namespace,
        bytes calldata bytecode,
        SourceIndexV2 sourceIndex,
        uint256[][] calldata context,
        uint256[] calldata inputs
    ) external view returns (uint256[] calldata stack, uint256[] calldata writes);
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {SourceIndexV2, EncodedDispatch} from "../../../interface/deprecated/IInterpreterV2.sol";

/// @title LibEncodedDispatch
/// @notice Establishes and implements a convention for encoding an interpreter
/// dispatch. Handles encoding of several things required for efficient dispatch.
library LibEncodedDispatch {
    /// Builds an `EncodedDispatch` from its constituent parts.
    /// @param expression The onchain address of the expression to run.
    /// @param sourceIndex The index of the source to run within the expression
    /// as an entrypoint.
    /// @param maxOutputs The maximum outputs the caller can meaningfully use.
    /// If the interpreter returns a larger stack than this it is merely wasting
    /// gas across the external call boundary.
    /// @return The encoded dispatch.
    function encode2(address expression, SourceIndexV2 sourceIndex, uint256 maxOutputs)
        internal
        pure
        returns (EncodedDispatch)
    {
        // Both source index and max outputs are expected to be compile time
        // constants, or at least significantly less than type(uint16).max.
        // Generally a real world implementation would hit gas limits long before
        // either of these values overflowed. Rather than add the gas of
        // conditionals and errors to check for overflow, we simply truncate the
        // values to uint16.
        return EncodedDispatch.wrap(
            (uint256(uint160(expression)) << 0x20) | (uint256(uint16(SourceIndexV2.unwrap(sourceIndex))) << 0x10)
                | uint256(uint16(maxOutputs))
        );
    }

    function decode2(EncodedDispatch dispatch) internal pure returns (address, SourceIndexV2, uint256) {
        return (
            address(uint160(EncodedDispatch.unwrap(dispatch) >> 0x20)),
            SourceIndexV2.wrap(uint256(uint16(EncodedDispatch.unwrap(dispatch) >> 0x10))),
            uint256(uint16(EncodedDispatch.unwrap(dispatch)))
        );
    }
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {StateNamespace, FullyQualifiedNamespace} from "../../interface/IInterpreterV3.sol";

library LibNamespace {
    /// Standard way to elevate a caller-provided state namespace to a universal
    /// namespace that is disjoint from all other caller-provided namespaces.
    /// Essentially just hashes the `msg.sender` into the state namespace as-is.
    ///
    /// This is deterministic such that the same combination of state namespace
    /// and caller will produce the same fully qualified namespace, even across
    /// multiple transactions/blocks.
    ///
    /// @param stateNamespace The state namespace as specified by the caller.
    /// @param sender The caller this namespace is bound to.
    /// @return qualifiedNamespace A fully qualified namespace that cannot
    /// collide with any other state namespace specified by any other caller.
    function qualifyNamespace(StateNamespace stateNamespace, address sender)
        internal
        pure
        returns (FullyQualifiedNamespace qualifiedNamespace)
    {
        assembly ("memory-safe") {
            mstore(0, stateNamespace)
            mstore(0x20, sender)
            qualifiedNamespace := keccak256(0, 0x40)
        }
    }
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {IERC3156FlashLender} from "./ierc3156/IERC3156FlashLender.sol";
import {
    EvaluableV3,
    IInterpreterCallerV3,
    SignedContextV1,
    IInterpreterV3,
    IInterpreterStoreV2
} from "../../lib/rain.interpreter.interface/src/interface/IInterpreterCallerV3.sol";

/// Import unmodified structures from older versions of `IOrderBook`.
import {ClearStateChange, ClearConfig, IO} from "./deprecated/v3/IOrderBookV3.sol";

/// Thrown when take orders is called with no orders.
error NoOrders();

/// Thrown when take orders is called with a zero maximum input.
error ZeroMaximumInput();

/// Config the order owner may provide to define their order. The `msg.sender`
/// that adds an order cannot modify the owner nor bypass the integrity check of
/// the expression deployer that they specify. However they MAY specify a
/// deployer with a corrupt integrity check, so counterparties and clearers MUST
/// check the DISpair of the order and avoid untrusted pairings.
/// @param evaluable Standard `EvaluableV3` used to evaluate the order.
/// @param validInputs As per `validInputs` on the `Order`.
/// @param validOutputs As per `validOutputs` on the `Order`.
/// @param nonce As per `nonce` on the `Order`.
/// @param secret Secret to use for cryptography related to the order. This is
/// useless on public chains. MAY be useful in confidential chains, such as to
/// encrypt event data that records the behaviour of the order.
/// @param meta Arbitrary bytes that will NOT be used in the order evaluation
/// but MUST be emitted as a Rain `MetaV1` when the order is placed so can be
/// used by offchain processes.
struct OrderConfigV3 {
    EvaluableV3 evaluable;
    IO[] validInputs;
    IO[] validOutputs;
    bytes32 nonce;
    bytes32 secret;
    bytes meta;
}

/// Config for an individual take order from the overall list of orders in a
/// call to `takeOrders`.
/// @param order The order being taken this iteration.
/// @param inputIOIndex The index of the input token in `order` to match with the
/// take order output.
/// @param outputIOIndex The index of the output token in `order` to match with
/// the take order input.
/// @param signedContext Optional additional signed context relevant to the
/// taken order.
struct TakeOrderConfigV3 {
    OrderV3 order;
    uint256 inputIOIndex;
    uint256 outputIOIndex;
    SignedContextV1[] signedContext;
}

/// Defines a fully deployed order ready to evaluate by Orderbook. Identical to
/// `Order` except for the newer `EvaluableV2`.
/// @param owner The owner of the order is the `msg.sender` that added the order.
/// @param evaluable Standard `EvaluableV2` with entrypoints for both
/// "calculate order" and "handle IO". The latter MAY be empty bytes, in which
/// case it will be skipped at runtime to save gas.
/// @param validInputs A list of input tokens that are economically equivalent
/// for the purpose of processing this order. Inputs are relative to the order
/// so these tokens will be sent to the owners vault.
/// @param validOutputs A list of output tokens that are economically equivalent
/// for the purpose of processing this order. Outputs are relative to the order
/// so these tokens will be sent from the owners vault.
/// @param nonce A unique value for the order that the owner can use to prevent
/// the order hash being predictable or collide with existing orders. This MAY
/// be useful to prevent `addOrder` noops for orders with identical logic, or
/// to hide information on confidential chains.
struct OrderV3 {
    address owner;
    EvaluableV3 evaluable;
    IO[] validInputs;
    IO[] validOutputs;
    bytes32 nonce;
}

/// Config for a list of orders to take sequentially as part of a `takeOrders`
/// call.
/// @param minimumInput Minimum input from the perspective of the order taker.
/// @param maximumInput Maximum input from the perspective of the order taker.
/// @param maximumIORatio Maximum IO ratio as calculated by the order being
/// taken. The input is from the perspective of the order so higher ratio means
/// worse deal for the order taker.
/// @param orders Ordered list of orders that will be taken until the limit is
/// hit. Takers are expected to prioritise orders that appear to be offering
/// better deals i.e. lower IO ratios. This prioritisation and sorting MUST
/// happen offchain, e.g. via. some simulator.
/// @param data If nonzero length, triggers `onTakeOrders` on the caller of
/// `takeOrders` with this data. This allows the caller to perform arbitrary
/// onchain actions between receiving their input tokens, before having to send
/// their output tokens.
struct TakeOrdersConfigV3 {
    uint256 minimumInput;
    uint256 maximumInput;
    uint256 maximumIORatio;
    TakeOrderConfigV3[] orders;
    bytes data;
}

/// A task combines evaluable logic with additional context to be run by
/// Orderbook. Tasks are expected to be provided to a primary call such as
/// `deposit`, `withdraw`, `addOrder`, `removeOrder` etc. to allow the caller
/// to run additional logic afterwards. This is useful for governance wrappers,
/// fee collectors, or other external systems that need to respond to the
/// primary call.
/// @param evaluable The evaluable logic to run as part of the task.
/// @param signedContext Additional context to be provided to the evaluable.
struct TaskV1 {
    EvaluableV3 evaluable;
    SignedContextV1[] signedContext;
}

/// Configuration for a quote request.
/// @param order The order to quote.
/// @param inputIOIndex The index of the input token in `order` to quote.
/// @param outputIOIndex The index of the output token in `order` to quote.
/// @param signedContext Optional additional signed context relevant to the
/// quote.
struct Quote {
    OrderV3 order;
    uint256 inputIOIndex;
    uint256 outputIOIndex;
    SignedContextV1[] signedContext;
}

/// @title IOrderBookV4
/// @notice An orderbook that deploys _strategies_ represented as interpreter
/// expressions rather than individual orders. The order book contract itself
/// behaves similarly to an `ERC4626` vault but with much more fine grained
/// control over how tokens are allocated and moved internally by their owners,
/// and without any concept of "shares". Token owners MAY deposit and withdraw
/// their tokens under arbitrary vault IDs on a per-token basis, then define
/// orders that specify how tokens move between vaults according to an expression.
/// The expression returns a maximum amount and a token input/output ratio from
/// the perpective of the order. When two expressions intersect, as in their
/// ratios are the inverse of each other, then tokens can move between vaults.
///
/// For example, consider order A with input TKNA and output TKNB with a constant
/// ratio of 100:1. This order in isolation has no ability to move tokens. If
/// an order B appears with input TKNB and output TKNA and a ratio of 1:100 then
/// this is a perfect match with order A. In this case 100 TKNA will move from
/// order B to order A and 1 TKNB will move from order A to order B.
///
/// IO ratios are always specified as input:output and are 18 decimal fixed point
/// values. The maximum amount that can be moved in the current clearance is also
/// set by the order expression as an 18 decimal fixed point value.
///
/// Typically orders will not clear when their match is exactly 1:1 as the
/// clearer needs to pay gas to process the match. Each order will get exactly
/// the ratio it calculates when it does clear so if there is _overlap_ in the
/// ratios then the clearer keeps the difference. In our above example, consider
/// order B asking a ratio of 1:110 instead of 1:100. In this case 100 TKNA will
/// move from order B to order A and 10 TKNA will move to the clearer's vault and
/// 1 TKNB will move from order A to order B. In the case of fixed prices this is
/// not very interesting as order B could more simply take order A directly for
/// cheaper rather than involving a third party. Indeed, Orderbook supports a
/// direct "take orders" method that works similar to a "market buy". In the case
/// of dynamic expression based ratios, it allows both order A and order B to
/// clear non-interactively according to their strategy, trading off active
/// management, dealing with front-running, MEV, etc. for zero-gas and
/// exact-ratio clearance.
///
/// The general invariant for clearing and take orders is:
///
/// ```
/// ratioA = InputA / OutputA
/// ratioB = InputB / OutputB
/// ratioA * ratioB = ( InputA * InputB ) / ( OutputA * OutputB )
/// OutputA >= InputB
/// OutputB >= InputA
///
/// ∴ ratioA * ratioB <= 1
/// ```
///
/// Orderbook is `IERC3156FlashLender` compliant with a 0 fee flash loan
/// implementation to allow external liquidity from other onchain DEXes to match
/// against orderbook expressions. All deposited tokens across all vaults are
/// available for flashloan, the flashloan MAY BE REPAID BY CALLING TAKE ORDER
/// such that Orderbook's liability to its vaults is decreased by an incoming
/// trade from the flashloan borrower. See `ZeroExOrderBookFlashBorrower` for
/// an example of how this works in practise.
///
/// Orderbook supports many to many input/output token relationship, for example
/// some order can specify an array of stables it would be willing to accept in
/// return for some ETH. This removes the need for a combinatorial explosion of
/// order strategies between like assets but introduces the issue of token
/// decimal handling. End users understand that "one" USDT is roughly equal to
/// "one" DAI, but onchain this is incorrect by _12 orders of magnitude_. This
/// is because "one" DAI is `1e18` tokens and "one" USDT is `1e6` tokens. The
/// orderbook is allowing orders to deploy expressions that define _economic
/// equivalence_ but this doesn't map 1:1 with numeric equivalence in a many to
/// many setup behind token decimal convensions. The solution is to require that
/// end users who place orders provide the decimals of each token they include
/// in their valid IO lists, and to calculate all amounts and ratios in their
/// expressions _as though they were 18 decimal fixed point values_. Orderbook
/// will then automatically rescale the expression values before applying the
/// final vault movements. If an order provides the "wrong" decimal values for
/// some token then it will simply calculate its own ratios and amounts
/// incorrectly which will either lead to no matching orders or a very bad trade
/// for the order owner. There is no way that misrepresenting decimals can attack
/// some other order by a counterparty. Orderbook DOES NOT read decimals from
/// tokens onchain because A. this would be gas for an external call to a cold
/// token contract and B. the ERC20 standard specifically states NOT to read
/// decimals from the interface onchain.
///
/// Token amounts and ratios returned by calculate order MUST be 18 decimal fixed
/// point values. Token amounts input to handle IO MUST be the exact absolute
/// values that move between the vaults, i.e. NOT rescaled to 18 decimals. The
/// author of the handle IO expression MUST use the token decimals and amounts to
/// rescale themselves if they want that logic, notably the expression author
/// will need to specify the desired rounding behaviour in the rescaling process.
///
/// When two orders clear there are NO TOKEN MOVEMENTS, only internal vault
/// balances are updated from the input and output vaults. Typically this results
/// in less gas per clear than calling external token transfers and also avoids
/// issues with reentrancy, allowances, external balances etc. This also means
/// that REBASING TOKENS AND TOKENS WITH DYNAMIC BALANCE ARE NOT SUPPORTED.
/// Orderbook ONLY WORKS IF TOKEN BALANCES ARE 1:1 WITH ADDITION/SUBTRACTION PER
/// VAULT MOVEMENT.
///
/// Dust due to rounding errors always favours the order. Output max is rounded
/// down and IO ratios are rounded up. Input and output amounts are always
/// converted to absolute values before applying to vault balances such that
/// orderbook always retains fully collateralised inventory of underlying token
/// balances to support withdrawals, with the caveat that dynamic token balanes
/// are not supported.
///
/// When an order clears it is NOT removed. Orders remain active until the owner
/// deactivates them. This is gas efficient as order owners MAY deposit more
/// tokens in a vault with an order against it many times and the order strategy
/// will continue to be clearable according to its expression. As vault IDs are
/// `bytes` values there are effectively infinite possible vaults for any token
/// so there is no limit to how many active orders any address can have at one
/// time. This also allows orders to be daisy chained arbitrarily where output
/// vaults for some order are the input vaults for some other order.
///
/// Expression storage is namespaced by order owner, so gets and sets are unique
/// to each onchain address. Order owners MUST TAKE CARE not to override their
/// storage sets globally across all their orders, which they can do most simply
/// by hashing the order hash into their get/set keys inside the expression. This
/// gives maximum flexibility for shared state across orders without allowing
/// order owners to attack and overwrite values stored by orders placed by their
/// counterparty.
///
/// Note that each order specifies its own interpreter and deployer so the
/// owner is responsible for not corrupting their own calculations with bad
/// interpreters. This also means the Orderbook MUST assume the interpreter, and
/// notably the interpreter's store, is malicious and guard against reentrancy
/// etc.
///
/// As Orderbook supports any expression that can run on any `IInterpreterV1` and
/// counterparties are available to the order, order strategies are free to
/// implement KYC/membership, tracking, distributions, stock, buybacks, etc. etc.
///
/// Main differences between `IOrderBookV3` and `IOderBookV4`:
/// - Orders support and expect `eval3` direct evaluation from calldata.
/// - Orders have preliminary support for confidential EVMs.
/// - Added `eval` that allows the caller to evaluate expressions directly.
/// - Added `post` to `deposit`, `withdraw`, `addOrder`, `removeOrder` which
///   allows evaluating expressions after the main action.
interface IOrderBookV4 is IERC3156FlashLender, IInterpreterCallerV3 {
    /// MUST be thrown by `deposit` if the amount is zero.
    /// @param sender `msg.sender` depositing tokens.
    /// @param token The token being deposited.
    /// @param vaultId The vault ID the tokens are being deposited under.
    error ZeroDepositAmount(address sender, address token, uint256 vaultId);

    /// MUST be thrown by `withdraw` if the amount _requested_ to withdraw is
    /// zero. The withdrawal MAY still not move any tokens if the vault balance
    /// is zero, or the withdrawal is used to repay a flash loan.
    /// @param sender `msg.sender` withdrawing tokens.
    /// @param token The token being withdrawn.
    /// @param vaultId The vault ID the tokens are being withdrawn from.
    error ZeroWithdrawTargetAmount(address sender, address token, uint256 vaultId);

    /// MUST be thrown by `addOrder` if the order has no associated calculation.
    error OrderNoSources();

    /// MUST be thrown by `addOrder` if the order has no associated handle IO.
    error OrderNoHandleIO();

    /// MUST be thrown by `addOrder` if the order has no inputs.
    error OrderNoInputs();

    /// MUST be thrown by `addOrder` if the order has no outputs.
    error OrderNoOutputs();

    /// Some tokens have been deposited to a vault.
    /// @param sender `msg.sender` depositing tokens. Delegated deposits are NOT
    /// supported.
    /// @param token The token being deposited.
    /// @param vaultId The vault ID the tokens are being deposited under.
    /// @param amount The amount of tokens deposited.
    event Deposit(address sender, address token, uint256 vaultId, uint256 amount);

    /// Some tokens have been withdrawn from a vault.
    /// @param sender `msg.sender` withdrawing tokens. Delegated withdrawals are
    /// NOT supported.
    /// @param token The token being withdrawn.
    /// @param vaultId The vault ID the tokens are being withdrawn from.
    /// @param targetAmount The amount of tokens requested to withdraw.
    /// @param amount The amount of tokens withdrawn, can be less than the
    /// target amount if the vault does not have the funds available to cover
    /// the target amount. For example an active order might move tokens before
    /// the withdraw completes.
    event Withdraw(address sender, address token, uint256 vaultId, uint256 targetAmount, uint256 amount);

    /// An order has been added to the orderbook. The order is permanently and
    /// always active according to its expression until/unless it is removed.
    /// @param sender `msg.sender` adding the order and is owner of the order.
    /// @param orderHash The hash of the order as it is recorded onchain. Only
    /// the hash is stored in Orderbook storage to avoid paying gas to store the
    /// entire order.
    /// @param order The newly added order. MUST be handed back as-is when
    /// clearing orders and contains derived information in addition to the order
    /// config that was provided by the order owner.
    event AddOrderV2(address sender, bytes32 orderHash, OrderV3 order);

    /// An order has been removed from the orderbook. This effectively
    /// deactivates it. Orders can be added again after removal.
    /// @param sender `msg.sender` removing the order and is owner of the order.
    /// @param orderHash The hash of the removed order.
    /// @param order The removed order.
    event RemoveOrderV2(address sender, bytes32 orderHash, OrderV3 order);

    /// Some order has been taken by `msg.sender`. This is the same as them
    /// placing inverse orders then immediately clearing them all, but costs less
    /// gas and is more convenient and reliable. Analogous to a market buy
    /// against the specified orders. Each order that is matched within a the
    /// `takeOrders` loop emits its own individual event.
    /// @param sender `msg.sender` taking the orders.
    /// @param config All config defining the orders to attempt to take.
    /// @param input The input amount from the perspective of sender.
    /// @param output The output amount from the perspective of sender.
    event TakeOrderV2(address sender, TakeOrderConfigV3 config, uint256 input, uint256 output);

    /// Emitted when attempting to match an order that either never existed or
    /// was removed. An event rather than an error so that we allow attempting
    /// many orders in a loop and NOT rollback on "best effort" basis to clear.
    /// @param sender `msg.sender` clearing the order that wasn't found.
    /// @param owner Owner of the order that was not found.
    /// @param orderHash Hash of the order that was not found.
    event OrderNotFound(address sender, address owner, bytes32 orderHash);

    /// Emitted when an order evaluates to a zero amount. An event rather than an
    /// error so that we allow attempting many orders in a loop and NOT rollback
    /// on a "best effort" basis to clear.
    /// @param sender `msg.sender` clearing the order that had a 0 amount.
    /// @param owner Owner of the order that evaluated to a 0 amount.
    /// @param orderHash Hash of the order that evaluated to a 0 amount.
    event OrderZeroAmount(address sender, address owner, bytes32 orderHash);

    /// Emitted when an order evaluates to a ratio exceeding the counterparty's
    /// maximum limit. An error rather than an error so that we allow attempting
    /// many orders in a loop and NOT rollback on a "best effort" basis to clear.
    /// @param sender `msg.sender` clearing the order that had an excess ratio.
    /// @param owner Owner of the order that had an excess ratio.
    /// @param orderHash Hash of the order that had an excess ratio.
    event OrderExceedsMaxRatio(address sender, address owner, bytes32 orderHash);

    /// Emitted before two orders clear. Covers both orders and includes all the
    /// state before anything is calculated.
    /// @param sender `msg.sender` clearing both orders.
    /// @param alice One of the orders.
    /// @param bob The other order.
    /// @param clearConfig Additional config required to process the clearance.
    event ClearV2(address sender, OrderV3 alice, OrderV3 bob, ClearConfig clearConfig);

    /// Emitted after two orders clear. Includes all final state changes in the
    /// vault balances, including the clearer's vaults.
    /// @param sender `msg.sender` clearing the order.
    /// @param clearStateChange The final vault state changes from the clearance.
    event AfterClear(address sender, ClearStateChange clearStateChange);

    /// Get the current balance of a vault for a given owner, token and vault ID.
    /// @param owner The owner of the vault.
    /// @param token The token the vault is for.
    /// @param vaultId The vault ID to read.
    /// @return balance The current balance of the vault.
    function vaultBalance(address owner, address token, uint256 vaultId) external view returns (uint256 balance);

    /// `msg.sender` entasks the provided tasks. This DOES NOT return
    /// any values, and MUST NOT modify any vault balances. Presumably the
    /// expressions will modify some internal state associated with active
    /// orders. If ANY of the expressions revert, the entire transaction MUST
    /// revert.
    function entask(TaskV1[] calldata tasks) external;

    /// `msg.sender` deposits tokens according to config. The config specifies
    /// the vault to deposit tokens under. Delegated depositing is NOT supported.
    /// Depositing DOES NOT mint shares (unlike ERC4626) so the overall vaulted
    /// experience is much simpler as there is always a 1:1 relationship between
    /// deposited assets and vault balances globally and individually. This
    /// mitigates rounding/dust issues, speculative behaviour on derived assets,
    /// possible regulatory issues re: whether a vault share is a security, code
    /// bloat on the vault, complex mint/deposit/withdraw/redeem 4-way logic,
    /// the need for preview functions, etc. etc.
    ///
    /// At the same time, allowing vault IDs to be specified by the depositor
    /// allows much more granular and direct control over token movements within
    /// Orderbook than either ERC4626 vault shares or mere contract-level ERC20
    /// allowances can facilitate.
    //
    /// Vault IDs are namespaced by the token address so there is no risk of
    /// collision between tokens. For example, vault ID 0 for token A is
    /// completely different to vault ID 0 for token B.
    ///
    /// `0` amount deposits are unsupported as underlying token contracts
    /// handle `0` value transfers differently and this would be a source of
    /// confusion. The order book MUST revert with `ZeroDepositAmount` if the
    /// amount is zero.
    ///
    /// @param token The token to deposit.
    /// @param vaultId The vault ID to deposit under.
    /// @param amount The amount of tokens to deposit.
    /// @param tasks Additional tasks to run after the deposit. Deposit
    /// information SHOULD be made available during evaluation in context.
    /// If ANY of the post tasks revert, the deposit MUST be reverted.
    function deposit2(address token, uint256 vaultId, uint256 amount, TaskV1[] calldata tasks) external;

    /// Allows the sender to withdraw any tokens from their own vaults. If the
    /// withrawer has an active flash loan debt denominated in the same token
    /// being withdrawn then Orderbook will merely reduce the debt and NOT send
    /// the amount of tokens repaid to the flashloan debt.
    ///
    /// MUST revert if the amount _requested_ to withdraw is zero. The withdrawal
    /// MAY still not move any tokens (without revert) if the vault balance is
    /// zero, or the withdrawal is used to repay a flash loan, or due to any
    /// other internal accounting.
    ///
    /// @param token The token to withdraw.
    /// @param vaultId The vault ID to withdraw from.
    /// @param targetAmount The amount of tokens to attempt to withdraw. MAY
    /// result in fewer tokens withdrawn if the vault balance is lower than the
    /// target amount. MAY NOT be zero, the order book MUST revert with
    /// `ZeroWithdrawTargetAmount` if the amount is zero.
    /// @param tasks Additional tasks to run after the withdraw. Withdraw
    /// information SHOULD be made available during evaluation in context.
    /// If ANY of the tasks revert, the withdraw MUST be reverted.
    function withdraw2(address token, uint256 vaultId, uint256 targetAmount, TaskV1[] calldata tasks) external;

    /// Returns true if the order exists, false otherwise.
    /// @param orderHash The hash of the order to check.
    /// @return exists True if the order exists, false otherwise.
    function orderExists(bytes32 orderHash) external view returns (bool exists);

    /// Quotes the provided order for the caller.
    /// The caller is considered to be the counterparty to the order, for the
    /// purposes of evaluating the quote. However, the caller's vault balances
    /// and/or tokens in wallet are not considered in the quote. This means the
    /// output max can exceed what the caller could actually pay for.
    /// Both the output max and io ratio are returned as 18 decimal fixed point
    /// values, ignoring any token decimals, so are not the literal amounts that
    /// would be moved in the order were it to clear.
    /// @param quoteConfig The configuration for the quote.
    /// @return exists True if the order exists, false otherwise.
    /// @return outputMax The maximum output amount that the order could send.
    /// Is `0` if the order does not exist.
    /// @return ioRatio The input:output ratio of the order. Is `0` if the order
    /// does not exist.
    function quote(Quote calldata quoteConfig)
        external
        view
        returns (bool exists, uint256 outputMax, uint256 ioRatio);

    /// Given an order config, deploys the expression and builds the full `Order`
    /// for the config, then records it as an active order. Delegated adding an
    /// order is NOT supported. The `msg.sender` that adds an order is ALWAYS
    /// the owner and all resulting vault movements are their own.
    ///
    /// MUST revert with `OrderNoSources` if the order has no associated
    /// calculation and `OrderNoHandleIO` if the order has no handle IO
    /// entrypoint. The calculation MUST return at least two values from
    /// evaluation, the maximum amount and the IO ratio. The handle IO entrypoint
    /// SHOULD return zero values from evaluation. Either MAY revert during
    /// evaluation on the interpreter, which MUST prevent the order from
    /// clearing.
    ///
    /// MUST revert with `OrderNoInputs` if the order has no inputs.
    /// MUST revert with `OrderNoOutputs` if the order has no outputs.
    ///
    /// If the order already exists, the order book MUST NOT change state, which
    /// includes not emitting an event. Instead it MUST return false. If the
    /// order book modifies state it MUST emit an `AddOrder` event and return
    /// true.
    ///
    /// @param config All config required to build an `Order`.
    /// @param tasks Additional tasks to run after the order is added.
    /// Order information SHOULD be made available during evaluation in context.
    /// If ANY of the tasks revert, the order MUST NOT be added.
    /// @return stateChanged True if the order was added, false if it already
    /// existed.
    function addOrder2(OrderConfigV3 calldata config, TaskV1[] calldata tasks) external returns (bool stateChanged);

    /// Order owner can remove their own orders. Delegated order removal is NOT
    /// supported and will revert. Removing an order multiple times or removing
    /// an order that never existed are valid, the event will be emitted and the
    /// transaction will complete with that order hash definitely, redundantly
    /// not live.
    /// @param order The `Order` data exactly as it was added.
    /// @param tasks Additional tasks to run after the order is removed.
    /// Order information SHOULD be made available during evaluation in context.
    /// If ANY of the tasks revert, the order MUST NOT be removed.
    /// @return stateChanged True if the order was removed, false if it did not
    /// exist.
    function removeOrder2(OrderV3 calldata order, TaskV1[] calldata tasks) external returns (bool stateChanged);

    /// Allows `msg.sender` to attempt to fill a list of orders in sequence
    /// without needing to place their own order and clear them. This works like
    /// a market buy but against a specific set of orders. Every order will
    /// looped over and calculated individually then filled maximally until the
    /// request input is reached for the `msg.sender`. The `msg.sender` is
    /// responsible for selecting the best orders at the time according to their
    /// criteria and MAY specify a maximum IO ratio to guard against an order
    /// spiking the ratio beyond what the `msg.sender` expected and is
    /// comfortable with. As orders may be removed and calculate their ratios
    /// dynamically, all issues fulfilling an order other than misconfiguration
    /// by the `msg.sender` are no-ops and DO NOT revert the transaction. This
    /// allows the `msg.sender` to optimistically provide a list of orders that
    /// they aren't sure will completely fill at a good price, and fallback to
    /// more reliable orders further down their list. Misconfiguration such as
    /// token mismatches are errors that revert as this is known and static at
    /// all times to the `msg.sender` so MUST be provided correctly. `msg.sender`
    /// MAY specify a minimum input that MUST be reached across all orders in the
    /// list, otherwise the transaction will revert, this MAY be set to zero.
    ///
    /// Exactly like withdraw, if there is an active flash loan for `msg.sender`
    /// they will have their outstanding loan reduced by the final input amount
    /// preferentially before sending any tokens. Notably this allows arb bots
    /// implemented as flash loan borrowers to connect orders against external
    /// liquidity directly by paying back the loan with a `takeOrders` call and
    /// outputting the result of the external trade.
    ///
    /// Rounding errors always favour the order never the `msg.sender`.
    ///
    /// @param config The constraints and list of orders to take, orders are
    /// processed sequentially in order as provided, there is NO ATTEMPT onchain
    /// to predict/filter/sort these orders other than evaluating them as
    /// provided. Inputs and outputs are from the perspective of `msg.sender`
    /// except for values specified by the orders themselves which are the from
    /// the perspective of that order.
    /// @return totalInput Total tokens sent to `msg.sender`, taken from order
    /// vaults processed.
    /// @return totalOutput Total tokens taken from `msg.sender` and distributed
    /// between vaults.
    function takeOrders2(TakeOrdersConfigV3 calldata config)
        external
        returns (uint256 totalInput, uint256 totalOutput);

    /// Allows `msg.sender` to match two live orders placed earlier by
    /// non-interactive parties and claim a bounty in the process. The clearer is
    /// free to select any two live orders on the order book for matching and as
    /// long as they have compatible tokens, ratios and amounts, the orders will
    /// clear. Clearing the orders DOES NOT remove them from the orderbook, they
    /// remain live until explicitly removed by their owner. Even if the input
    /// vault balances are completely emptied, the orders remain live until
    /// removed. This allows order owners to deploy a strategy over a long period
    /// of time and periodically top up the input vaults. Clearing two orders
    /// from the same owner is disallowed.
    ///
    /// Any mismatch in the ratios between the two orders will cause either more
    /// inputs than there are available outputs (transaction will revert) or less
    /// inputs than there are available outputs. In the latter case the excess
    /// outputs are given to the `msg.sender` of clear, to the vaults they
    /// specify in the clear config. This not only incentivises "automatic" clear
    /// calls for both alice and bob, but incentivises _prioritising greater
    /// ratio differences_ with a larger bounty. The second point is important
    /// because it implicitly prioritises orders that are further from the
    /// current market price, thus putting constant increasing pressure on the
    /// entire system the further it drifts from the norm, no matter how esoteric
    /// the individual order expressions and sizings might be.
    ///
    /// All else equal there are several factors that would impact how reliably
    /// some order clears relative to the wider market, such as:
    ///
    /// - Bounties are effectively percentages of cleared amounts so larger
    ///   orders have larger bounties and cover gas costs more easily
    /// - High gas on the network means that orders are harder to clear
    ///   profitably so the negative spread of the ratios will need to be larger
    /// - Complex and stateful expressions cost more gas to evalulate so the
    ///   negative spread will need to be larger
    /// - Erratic behavior of the order owner could reduce the willingness of
    ///   third parties to interact if it could result in wasted gas due to
    ///   orders suddently being removed before clearance etc.
    /// - Dynamic and highly volatile words used in the expression could be
    ///   ignored or low priority by clearers who want to be sure that they can
    ///   accurately predict the ratios that they include in their clearance
    /// - Geopolitical issues such as sanctions and regulatory restrictions could
    ///   cause issues for certain owners and clearers
    ///
    /// @param alice Some order to clear.
    /// @param bob Another order to clear.
    /// @param clearConfig Additional configuration for the clearance such as
    /// how to handle the bounty payment for the `msg.sender`.
    /// @param aliceSignedContext Optional signed context that is relevant to A.
    /// @param bobSignedContext Optional signed context that is relevant to B.
    function clear2(
        OrderV3 memory alice,
        OrderV3 memory bob,
        ClearConfig calldata clearConfig,
        SignedContextV1[] memory aliceSignedContext,
        SignedContextV1[] memory bobSignedContext
    ) external;
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {IOrderBookV4OrderTaker} from "../IOrderBookV4OrderTaker.sol";
import {TakeOrdersConfigV3, IOrderBookV4, TaskV1} from "../IOrderBookV4.sol";
import {EvaluableV3} from "../IOrderBookV4.sol";

interface IOrderBookV4ArbOrderTakerV2 is IOrderBookV4OrderTaker {
    function arb3(IOrderBookV4 orderBook, TakeOrdersConfigV3 calldata takeOrders, TaskV1 calldata task)
        external
        payable;
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {StateNamespace, FullyQualifiedNamespace, NO_STORE} from "./deprecated/IInterpreterStoreV1.sol";

/// @title IInterpreterStoreV2
/// @notice Tracks state changes on behalf of an interpreter. A single store can
/// handle state changes for many calling contracts, many interpreters and many
/// expressions. The store is responsible for ensuring that applying these state
/// changes is safe from key collisions with calls to `set` from different
/// `msg.sender` callers. I.e. it MUST NOT be possible for a caller to modify the
/// state changes associated with some other caller.
///
/// The store defines the shape of its own state changes, which is opaque to the
/// calling contract. For example, some store may treat the list of state changes
/// as a pairwise key/value set, and some other store may treat it as a literal
/// list to be stored as-is.
///
/// Each interpreter decides for itself which store to use based on the
/// compatibility of its own opcodes.
///
/// The store MUST assume the state changes have been corrupted by the calling
/// contract due to bugs or malicious intent, and enforce state isolation between
/// callers despite arbitrarily invalid state changes. The store MUST revert if
/// it can detect invalid state changes, such as a key/value list having an odd
/// number of items, but this MAY NOT be possible if the corruption is
/// undetectable.
interface IInterpreterStoreV2 {
    /// MUST be emitted by the store on `set` to its internal storage.
    /// @param namespace The fully qualified namespace that the store is setting.
    /// @param key The key that the store is setting.
    /// @param value The value that the store is setting.
    event Set(FullyQualifiedNamespace namespace, uint256 key, uint256 value);

    /// Mutates the interpreter store in bulk. The bulk values are provided in
    /// the form of a `uint256[]` which can be treated e.g. as pairwise keys and
    /// values to be stored in a Solidity mapping. The `IInterpreterStoreV2`
    /// defines the meaning of the `uint256[]` for its own storage logic.
    ///
    /// @param namespace The unqualified namespace for the set that MUST be
    /// fully qualified by the `IInterpreterStoreV2` to prevent key collisions
    /// between callers. The fully qualified namespace forms a compound key with
    /// the keys for each value to set.
    /// @param kvs The list of changes to apply to the store's internal state.
    function set(StateNamespace namespace, uint256[] calldata kvs) external;

    /// Given a fully qualified namespace and key, return the associated value.
    /// Ostensibly the interpreter can use this to implement opcodes that read
    /// previously set values. The interpreter MUST apply the same qualification
    /// logic as the store that it uses to guarantee consistent round tripping of
    /// data and prevent malicious behaviours. Technically also allows onchain
    /// reads of any set value from any contract, not just interpreters, but in
    /// this case readers MUST be aware and handle inconsistencies between get
    /// and set while the state changes are still in memory in the calling
    /// context and haven't yet been persisted to the store.
    ///
    /// `IInterpreterStoreV2` uses the same fallback behaviour for unset keys as
    /// Solidity. Specifically, any UNSET VALUES SILENTLY FALLBACK TO `0`.
    /// @param namespace The fully qualified namespace to get a single value for.
    /// @param key The key to get the value for within the namespace.
    /// @return The value OR ZERO IF NOT SET.
    function get(FullyQualifiedNamespace namespace, uint256 key) external view returns (uint256);
}

File 16 of 55 : OrderBookV4ArbCommon.sol
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.19;

import {EvaluableV3, SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV3.sol";
import {
    IInterpreterV3,
    SourceIndexV2,
    DEFAULT_STATE_NAMESPACE
} from "rain.interpreter.interface/interface/IInterpreterV3.sol";
import {IOrderBookV4, TaskV1} from "rain.orderbook.interface/interface/IOrderBookV4.sol";
import {LibContext} from "rain.interpreter.interface/lib/caller/LibContext.sol";
import {LibNamespace} from "rain.interpreter.interface/lib/ns/LibNamespace.sol";
import {LibEvaluable} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol";

/// Configuration for an arb contract to construct.
/// @param orderBook The `OrderBook` contract to arb against.
/// @param tasks The tasks to use as post for each arb.
/// @param implementationData The constructor data for the specific
/// implementation of the arb contract.
struct OrderBookV4ArbConfigV2 {
    address orderBook;
    TaskV1 task;
    bytes implementationData;
}

/// Thrown when the task does not match the expected hash.
error WrongTask();

/// @dev "Before arb" is evaluated before the flash loan is taken. Ostensibly
/// allows for some kind of access control to the arb.
SourceIndexV2 constant BEFORE_ARB_SOURCE_INDEX = SourceIndexV2.wrap(0);

abstract contract OrderBookV4ArbCommon {
    using LibEvaluable for EvaluableV3;

    event Construct(address sender, OrderBookV4ArbConfigV2 config);

    bytes32 public immutable iTaskHash = 0;

    constructor(OrderBookV4ArbConfigV2 memory config) {
        // Emit events before any external calls are made.
        emit Construct(msg.sender, config);

        if (config.task.evaluable.bytecode.length != 0) {
            iTaskHash = keccak256(abi.encode(config.task));
        }
    }

    modifier onlyValidTask(TaskV1 memory task) {
        if (iTaskHash != bytes32(0) && iTaskHash != keccak256(abi.encode(task))) {
            revert WrongTask();
        }
        _;
    }
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {LibUint256Array} from "rain.solmem/lib/LibUint256Array.sol";
import {LibHashNoAlloc, HASH_NIL} from "rain.lib.hash/LibHashNoAlloc.sol";

import {SignatureChecker} from "openzeppelin-contracts/contracts/utils/cryptography/SignatureChecker.sol";
import {ECDSA} from "openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol";

import {
    SignedContextV1,
    SIGNED_CONTEXT_SIGNER_OFFSET,
    SIGNED_CONTEXT_SIGNATURE_OFFSET,
    SIGNED_CONTEXT_CONTEXT_OFFSET
} from "../../interface/IInterpreterCallerV3.sol";

/// Thrown when the ith signature from a list of signed contexts is invalid.
error InvalidSignature(uint256 i);

uint256 constant CONTEXT_BASE_COLUMN = 0;
uint256 constant CONTEXT_BASE_ROWS = 2;

uint256 constant CONTEXT_BASE_ROW_SENDER = 0;
uint256 constant CONTEXT_BASE_ROW_CALLING_CONTRACT = 1;

/// @title LibContext
/// @notice Conventions for working with context as a calling contract. All of
/// this functionality is OPTIONAL but probably useful for the majority of use
/// cases. By building and authenticating onchain, caller provided and signed
/// contexts all in a standard way the overall usability of context is greatly
/// improved for expression authors and readers. Any calling contract that can
/// match the context expectations of an existing expression is one large step
/// closer to compatibility and portability, inheriting network effects of what
/// has already been authored elsewhere.
library LibContext {
    using LibUint256Array for uint256[];

    /// The base context is the `msg.sender` and address of the calling contract.
    /// As the interpreter itself is called via an external interface and may be
    /// statically calling itself, it MAY NOT have any ability to inspect either
    /// of these values. Even if this were not the case the calling contract
    /// cannot assume the existence of some opcode(s) in the interpreter that
    /// inspect the caller, so providing these two values as context is
    /// sufficient to decouple the calling contract from the interpreter. It is
    /// STRONGLY RECOMMENDED that even if the calling contract has "no context"
    /// that it still provides this base to every `eval`.
    ///
    /// Calling contracts DO NOT need to call this directly. It is built and
    /// merged automatically into the standard context built by `build`.
    ///
    /// @return The `msg.sender` and address of the calling contract using this
    /// library, as a context-compatible array.
    function base() internal view returns (uint256[] memory) {
        return LibUint256Array.arrayFrom(uint256(uint160(msg.sender)), uint256(uint160(address(this))));
    }

    /// Standard hashing process over a single `SignedContextV1`. Notably used
    /// to hash a list as `SignedContextV1[]` but could also be used to hash a
    /// single `SignedContextV1` in isolation. Avoids allocating memory by
    /// hashing each struct field in sequence within the memory scratch space.
    /// @param signedContext The signed context to hash.
    /// @param hashed The hashed signed context.
    function hash(SignedContextV1 memory signedContext) internal pure returns (bytes32 hashed) {
        uint256 signerOffset = SIGNED_CONTEXT_SIGNER_OFFSET;
        uint256 contextOffset = SIGNED_CONTEXT_CONTEXT_OFFSET;
        uint256 signatureOffset = SIGNED_CONTEXT_SIGNATURE_OFFSET;

        assembly ("memory-safe") {
            mstore(0, keccak256(add(signedContext, signerOffset), 0x20))

            let context_ := mload(add(signedContext, contextOffset))
            mstore(0x20, keccak256(add(context_, 0x20), mul(mload(context_), 0x20)))

            mstore(0, keccak256(0, 0x40))

            let signature_ := mload(add(signedContext, signatureOffset))
            mstore(0x20, keccak256(add(signature_, 0x20), mload(signature_)))

            hashed := keccak256(0, 0x40)
        }
    }

    /// Standard hashing process over a list of signed contexts. Situationally
    /// useful if the calling contract wants to record that it has seen a set of
    /// signed data then later compare it against some input (e.g. to ensure that
    /// many calls of some function all share the same input values). Note that
    /// unlike the internals of `build`, this hashes over the signer and the
    /// signature, to ensure that some data cannot be re-signed and used under
    /// a different provenance later.
    /// @param signedContexts The list of signed contexts to hash over.
    /// @return hashed The hash of the signed contexts.
    function hash(SignedContextV1[] memory signedContexts) internal pure returns (bytes32 hashed) {
        uint256 cursor;
        uint256 end;
        bytes32 hashNil = HASH_NIL;
        assembly ("memory-safe") {
            cursor := add(signedContexts, 0x20)
            end := add(cursor, mul(mload(signedContexts), 0x20))
            mstore(0, hashNil)
        }

        SignedContextV1 memory signedContext;
        bytes32 mem0;
        while (cursor < end) {
            assembly ("memory-safe") {
                signedContext := mload(cursor)
                // Subhash will write to 0 for its own hashing so keep a copy
                // before it gets overwritten.
                mem0 := mload(0)
            }
            bytes32 subHash = hash(signedContext);
            assembly ("memory-safe") {
                mstore(0, mem0)
                mstore(0x20, subHash)
                mstore(0, keccak256(0, 0x40))
                cursor := add(cursor, 0x20)
            }
        }
        assembly ("memory-safe") {
            hashed := mload(0)
        }
    }

    /// Builds a standard 2-dimensional context array from base, calling and
    /// signed contexts. Note that "columns" of a context array refer to each
    /// `uint256[]` and each item within a `uint256[]` is a "row".
    ///
    /// @param baseContext Anything the calling contract can provide which MAY
    /// include input from the `msg.sender` of the calling contract. The default
    /// base context from `LibContext.base()` DOES NOT need to be provided by the
    /// caller, this matrix MAY be empty and will be simply merged into the final
    /// context. The base context matrix MUST contain a consistent number of
    /// columns from the calling contract so that the expression can always
    /// predict how many unsigned columns there will be when it runs.
    /// @param signedContexts Signed contexts are provided by the `msg.sender`
    /// but signed by a third party. The expression (author) defines _who_ may
    /// sign and the calling contract authenticates the signature over the
    /// signed data. Technically `build` handles all the authentication inline
    /// for the calling contract so if some context builds it can be treated as
    /// authentic. The builder WILL REVERT if any of the signatures are invalid.
    /// Note two things about the structure of the final built context re: signed
    /// contexts:
    /// - The first column is a list of the signers in order of what they signed
    /// - The `msg.sender` can provide an arbitrary number of signed contexts so
    ///   expressions DO NOT know exactly how many columns there are.
    /// The expression is responsible for defining e.g. a domain separator in a
    /// position that would force signed context to be provided in the "correct"
    /// order, rather than relying on the `msg.sender` to honestly present data
    /// in any particular structure/order.
    function build(uint256[][] memory baseContext, SignedContextV1[] memory signedContexts)
        internal
        view
        returns (uint256[][] memory)
    {
        unchecked {
            uint256[] memory signers = new uint256[](signedContexts.length);

            // - LibContext.base() + whatever we are provided.
            // - signed contexts + signers if they exist else nothing.
            uint256 contextLength = 1 + baseContext.length + (signedContexts.length > 0 ? signedContexts.length + 1 : 0);

            uint256[][] memory context = new uint256[][](contextLength);
            uint256 offset = 0;
            context[offset] = LibContext.base();

            for (uint256 i = 0; i < baseContext.length; i++) {
                offset++;
                context[offset] = baseContext[i];
            }

            if (signedContexts.length > 0) {
                offset++;
                context[offset] = signers;

                for (uint256 i = 0; i < signedContexts.length; i++) {
                    if (
                        // Unlike `LibContext.hash` we can only hash over
                        // the context as it's impossible for a signature
                        // to sign itself.
                        // Note the use of encodePacked here over a
                        // single array, not including the length. This
                        // would be a security issue if multiple dynamic
                        // length values were hashed over together as
                        // then many possible inputs could collide with
                        // a single encoded output.
                        !SignatureChecker.isValidSignatureNow(
                            signedContexts[i].signer,
                            ECDSA.toEthSignedMessageHash(LibHashNoAlloc.hashWords(signedContexts[i].context)),
                            signedContexts[i].signature
                        )
                    ) {
                        revert InvalidSignature(i);
                    }

                    signers[i] = uint256(uint160(signedContexts[i].signer));
                    offset++;
                    context[offset] = signedContexts[i].context;
                }
            }

            return context;
        }
    }
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.25;

import {LibPointer, Pointer} from "rain.solmem/lib/LibPointer.sol";
import {LibBytes} from "rain.solmem/lib/LibBytes.sol";
import {LibMemCpy} from "rain.solmem/lib/LibMemCpy.sol";
import {
    StackSizingsNotMonotonic,
    TruncatedSource,
    UnexpectedTrailingOffsetBytes,
    TruncatedHeader,
    TruncatedHeaderOffsets,
    UnexpectedSources,
    SourceIndexOutOfBounds
} from "../../error/ErrBytecode.sol";

/// @title LibBytecode
/// @notice A library for inspecting the bytecode of an expression. Largely
/// focused on reading the source headers rather than the opcodes themselves.
/// Designed to be efficient enough to be used in the interpreter directly.
/// As such, it is not particularly safe, notably it always assumes that the
/// headers are not lying about the structure and runtime behaviour of the
/// bytecode. This is by design as it allows much more simple, efficient and
/// decoupled implementation of authoring/parsing logic, which makes the author
/// of an expression responsible for producing well formed bytecode, such as
/// balanced LHS/RHS stacks. The deployment integrity checks are responsible for
/// checking that the headers match the structure and behaviour of the bytecode.
library LibBytecode {
    using LibPointer for Pointer;
    using LibBytes for bytes;
    using LibMemCpy for Pointer;

    /// The number of sources in the bytecode.
    /// If the bytecode is empty, returns 0.
    /// Otherwise, returns the first byte of the bytecode, which is the number
    /// of sources.
    /// Implies that 0x and 0x00 are equivalent, both having 0 sources. For this
    /// reason, contracts that handle bytecode MUST NOT rely on simple data
    /// length checks to determine if the bytecode is empty or not.
    /// DOES NOT check the integrity or even existence of the sources.
    /// @param bytecode The bytecode to inspect.
    /// @return count The number of sources in the bytecode.
    function sourceCount(bytes memory bytecode) internal pure returns (uint256 count) {
        if (bytecode.length == 0) {
            return 0;
        }
        assembly ("memory-safe") {
            // The first byte of rain bytecode is the count of how many sources
            // there are.
            count := byte(0, mload(add(bytecode, 0x20)))
        }
    }

    /// Checks the structural integrity of the bytecode from the perspective of
    /// potential out of bounds reads. Will revert if the bytecode is not
    /// well-formed. This check MUST be done BEFORE any attempts at per-opcode
    /// integrity checks, as the per-opcode checks assume that the headers define
    /// valid regions in memory to iterate over.
    ///
    /// Checks:
    /// - The offsets are populated according to the source count.
    /// - The offsets point to positions within the bytecode `bytes`.
    /// - There exists at least the 4 byte header for each source at the offset,
    ///   within the bounds of the bytecode `bytes`.
    /// - The number of opcodes specified in the header of each source locates
    ///   the end of the source exactly at either the offset of the next source
    ///   or the end of the bytecode `bytes`.
    function checkNoOOBPointers(bytes memory bytecode) internal pure {
        unchecked {
            uint256 count = sourceCount(bytecode);
            // The common case is that there are more than 0 sources.
            if (count > 0) {
                uint256 sourcesRelativeStart = 1 + count * 2;
                if (sourcesRelativeStart > bytecode.length) {
                    revert TruncatedHeaderOffsets(bytecode);
                }
                uint256 sourcesStart;
                assembly ("memory-safe") {
                    sourcesStart := add(bytecode, add(0x20, sourcesRelativeStart))
                }

                // Start at the end of the bytecode and work backwards. Find the
                // last unchecked relative offset, follow it, read the opcode
                // count from the header, and check that ends at the end cursor.
                // Set the end cursor to the relative offset then repeat until
                // there are no more unchecked relative offsets. The endCursor
                // as a relative offset must be 0 at the end of this process
                // (i.e. the first relative offset is always 0).
                uint256 endCursor;
                assembly ("memory-safe") {
                    endCursor := add(bytecode, add(0x20, mload(bytecode)))
                }
                // This cursor points at the 2 byte relative offset that we need
                // to check next.
                uint256 uncheckedOffsetCursor;
                uint256 end;
                assembly ("memory-safe") {
                    uncheckedOffsetCursor := add(bytecode, add(0x21, mul(sub(count, 1), 2)))
                    end := add(bytecode, 0x21)
                }

                while (uncheckedOffsetCursor >= end) {
                    // Read the relative offset from the bytecode.
                    uint256 relativeOffset;
                    assembly ("memory-safe") {
                        relativeOffset := shr(0xF0, mload(uncheckedOffsetCursor))
                    }
                    uint256 absoluteOffset = sourcesStart + relativeOffset;

                    // Check that the 4 byte header is within the upper bound
                    // established by the end cursor before attempting to read
                    // from it.
                    uint256 headerEnd = absoluteOffset + 4;
                    if (headerEnd > endCursor) {
                        revert TruncatedHeader(bytecode);
                    }

                    // The ops count is the first byte of the header.
                    uint256 opsCount;
                    {
                        // The stack allocation, inputs, and outputs are the next
                        // 3 bytes of the header. We can't know exactly what they
                        // need to be according to the opcodes without checking
                        // every opcode implementation, but we can check that
                        // they satisfy the invariant
                        // `inputs <= outputs <= stackAllocation`.
                        // Note that the outputs may include the inputs, as the
                        // outputs is merely the final stack size.
                        uint256 stackAllocation;
                        uint256 inputs;
                        uint256 outputs;
                        assembly ("memory-safe") {
                            let data := mload(absoluteOffset)
                            opsCount := byte(0, data)
                            stackAllocation := byte(1, data)
                            inputs := byte(2, data)
                            outputs := byte(3, data)
                        }

                        if (inputs > outputs || outputs > stackAllocation) {
                            revert StackSizingsNotMonotonic(bytecode, relativeOffset);
                        }
                    }

                    // The ops count is the number of 4 byte opcodes in the
                    // source. Check that the end of the source is at the end
                    // cursor.
                    uint256 sourceEnd = headerEnd + opsCount * 4;
                    if (sourceEnd != endCursor) {
                        revert TruncatedSource(bytecode);
                    }

                    // Move the end cursor to the start of the header.
                    endCursor = absoluteOffset;
                    // Move the unchecked offset cursor to the previous offset.
                    uncheckedOffsetCursor -= 2;
                }

                // If the end cursor is not pointing at the absolute start of the
                // sources, then somehow the bytecode has malformed data between
                // the offsets and the sources.
                if (endCursor != sourcesStart) {
                    revert UnexpectedTrailingOffsetBytes(bytecode);
                }
            } else {
                // If there are no sources the bytecode is either 0 length or a
                // single 0 byte, which we already implicity checked by reaching
                // this code path. Ensure the bytecode has no trailing bytes.
                if (bytecode.length > 1) {
                    revert UnexpectedSources(bytecode);
                }
            }
        }
    }

    /// The relative byte offset of a source in the bytecode.
    /// This is the offset from the start of the first source header, which is
    /// after the source count byte and the source offsets.
    /// This function DOES NOT check that the relative offset is within the
    /// bounds of the bytecode. Callers MUST `checkNoOOBPointers` BEFORE
    /// attempting to traverse the bytecode, otherwise the relative offset MAY
    /// point to memory outside the bytecode `bytes`.
    /// @param bytecode The bytecode to inspect.
    /// @param sourceIndex The index of the source to inspect.
    /// @return offset The relative byte offset of the source in the bytecode.
    function sourceRelativeOffset(bytes memory bytecode, uint256 sourceIndex) internal pure returns (uint256 offset) {
        // If the source index requested is out of bounds, revert.
        if (sourceIndex >= sourceCount(bytecode)) {
            revert SourceIndexOutOfBounds(sourceIndex, bytecode);
        }
        assembly ("memory-safe") {
            // After the first byte, all the relative offset pointers are
            // stored sequentially as 16 bit values.
            offset := and(mload(add(add(bytecode, 3), mul(sourceIndex, 2))), 0xFFFF)
        }
    }

    /// The absolute byte pointer of a source in the bytecode. Points to the
    /// header of the source, NOT the first opcode.
    /// This function DOES NOT check that the source index is within the bounds
    /// of the bytecode. Callers MUST `checkNoOOBPointers` BEFORE attempting to
    /// traverse the bytecode, otherwise the relative offset MAY point to memory
    /// outside the bytecode `bytes`.
    /// @param bytecode The bytecode to inspect.
    /// @param sourceIndex The index of the source to inspect.
    /// @return pointer The absolute byte pointer of the source in the bytecode.
    function sourcePointer(bytes memory bytecode, uint256 sourceIndex) internal pure returns (Pointer pointer) {
        unchecked {
            uint256 sourcesStartOffset = 1 + sourceCount(bytecode) * 2;
            uint256 offset = sourceRelativeOffset(bytecode, sourceIndex);
            assembly ("memory-safe") {
                pointer := add(add(add(bytecode, 0x20), sourcesStartOffset), offset)
            }
        }
    }

    /// The number of opcodes in a source.
    /// This function DOES NOT check that the source index is within the bounds
    /// of the bytecode. Callers MUST `checkNoOOBPointers` BEFORE attempting to
    /// traverse the bytecode, otherwise the relative offset MAY point to memory
    /// outside the bytecode `bytes`.
    /// @param bytecode The bytecode to inspect.
    /// @param sourceIndex The index of the source to inspect.
    /// @return opsCount The number of opcodes in the source.
    function sourceOpsCount(bytes memory bytecode, uint256 sourceIndex) internal pure returns (uint256 opsCount) {
        unchecked {
            Pointer pointer = sourcePointer(bytecode, sourceIndex);
            assembly ("memory-safe") {
                opsCount := byte(0, mload(pointer))
            }
        }
    }

    /// The number of stack slots allocated by a source. This is the number of
    /// 32 byte words that MUST be allocated for the stack for the given source
    /// index to avoid memory corruption when executing the source.
    /// This function DOES NOT check that the source index is within the bounds
    /// of the bytecode. Callers MUST `checkNoOOBPointers` BEFORE attempting to
    /// traverse the bytecode, otherwise the relative offset MAY point to memory
    /// outside the bytecode `bytes`.
    /// @param bytecode The bytecode to inspect.
    /// @param sourceIndex The index of the source to inspect.
    /// @return allocation The number of stack slots allocated by the source.
    function sourceStackAllocation(bytes memory bytecode, uint256 sourceIndex)
        internal
        pure
        returns (uint256 allocation)
    {
        unchecked {
            Pointer pointer = sourcePointer(bytecode, sourceIndex);
            assembly ("memory-safe") {
                allocation := byte(1, mload(pointer))
            }
        }
    }

    /// The number of inputs and outputs of a source.
    /// This function DOES NOT check that the source index is within the bounds
    /// of the bytecode. Callers MUST `checkNoOOBPointers` BEFORE attempting to
    /// traverse the bytecode, otherwise the relative offset MAY point to memory
    /// outside the bytecode `bytes`.
    /// Note that both the inputs and outputs are always returned togther, this
    /// is because the caller SHOULD be checking both together whenever using
    /// some bytecode. Returning two values is more efficient than two separate
    /// function calls.
    /// @param bytecode The bytecode to inspect.
    /// @param sourceIndex The index of the source to inspect.
    /// @return inputs The number of inputs of the source.
    /// @return outputs The number of outputs of the source.
    function sourceInputsOutputsLength(bytes memory bytecode, uint256 sourceIndex)
        internal
        pure
        returns (uint256 inputs, uint256 outputs)
    {
        unchecked {
            Pointer pointer = sourcePointer(bytecode, sourceIndex);
            assembly ("memory-safe") {
                let data := mload(pointer)
                inputs := byte(2, data)
                outputs := byte(3, data)
            }
        }
    }

    /// Backwards compatibility with the old way of representing sources.
    /// Requires allocation and copying so it isn't particularly efficient, but
    /// allows us to use the new bytecode format with old interpreter code. Not
    /// recommended for production code but useful for testing.
    function bytecodeToSources(bytes memory bytecode) internal pure returns (bytes[] memory) {
        unchecked {
            uint256 count = sourceCount(bytecode);
            bytes[] memory sources = new bytes[](count);
            for (uint256 i = 0; i < count; i++) {
                // Skip over the prefix 4 bytes.
                Pointer pointer = sourcePointer(bytecode, i).unsafeAddBytes(4);
                uint256 length = sourceOpsCount(bytecode, i) * 4;
                bytes memory source = new bytes(length);
                pointer.unsafeCopyBytesTo(source.dataPointer(), length);
                // Move the opcode index one byte for each opcode, into the input
                // position, as legacly sources did not have input bytes.
                assembly ("memory-safe") {
                    for {
                        let cursor := add(source, 0x20)
                        let end := add(cursor, length)
                    } lt(cursor, end) { cursor := add(cursor, 4) } {
                        mstore8(add(cursor, 1), byte(0, mload(cursor)))
                        mstore8(cursor, 0)
                    }
                }
                sources[i] = source;
            }
            return sources;
        }
    }
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.19;

import {
    CONTEXT_BASE_ROWS,
    CONTEXT_BASE_ROW_SENDER,
    CONTEXT_BASE_ROW_CALLING_CONTRACT,
    CONTEXT_BASE_COLUMN
} from "rain.interpreter.interface/lib/caller/LibContext.sol";
import {EvaluableV3, TaskV1} from "rain.orderbook.interface/interface/IOrderBookV4.sol";
import {SourceIndexV2, StateNamespace} from "rain.interpreter.interface/interface/IInterpreterV3.sol";
import {LibNamespace} from "rain.interpreter.interface/lib/ns/LibNamespace.sol";
import {LibContext} from "rain.interpreter.interface/lib/caller/LibContext.sol";

/// @dev Orderbook context is actually fairly complex. The calling context column
/// is populated before calculate order, but the remaining columns are only
/// available to handle IO as they depend on the full evaluation of calculuate
/// order, and cross referencing against the same from the counterparty, as well
/// as accounting limits such as current vault balances, etc.
/// The token address and decimals for vault inputs and outputs IS available to
/// the calculate order entrypoint, but not the final vault balances/diff.
uint256 constant CALLING_CONTEXT_COLUMNS = 4;

uint256 constant CONTEXT_COLUMNS = CALLING_CONTEXT_COLUMNS + 1;

/// @dev Contextual data available to both calculate order and handle IO. The
/// order hash, order owner and order counterparty. IMPORTANT NOTE that the
/// typical base context of an order with the caller will often be an unrelated
/// clearer of the order rather than the owner or counterparty.
uint256 constant CONTEXT_CALLING_CONTEXT_COLUMN = 1;
uint256 constant CONTEXT_CALLING_CONTEXT_ROWS = 3;

uint256 constant CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH = 0;
uint256 constant CONTEXT_CALLING_CONTEXT_ROW_ORDER_OWNER = 1;
uint256 constant CONTEXT_CALLING_CONTEXT_ROW_ORDER_COUNTERPARTY = 2;

uint256 constant CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_TOKEN = 0;
uint256 constant CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_ID = 1;
uint256 constant CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_BALANCE = 2;
uint256 constant CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_AMOUNT = 3;

uint256 constant CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TOKEN = 0;
uint256 constant CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_ID = 1;
uint256 constant CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_BALANCE = 2;
uint256 constant CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_AMOUNT = 3;
uint256 constant CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TARGET_AMOUNT = 4;

/// @dev Calculations column contains the DECIMAL RESCALED calculations but
/// otherwise provided as-is according to calculate order entrypoint
uint256 constant CONTEXT_CALCULATIONS_COLUMN = 2;
uint256 constant CONTEXT_CALCULATIONS_ROWS = 2;

uint256 constant CONTEXT_CALCULATIONS_ROW_MAX_OUTPUT = 0;
uint256 constant CONTEXT_CALCULATIONS_ROW_IO_RATIO = 1;

/// @dev Vault inputs are the literal token amounts and vault balances before and
/// after for the input token from the perspective of the order. MAY be
/// significantly different to the calculated amount due to insufficient vault
/// balances from either the owner or counterparty, etc.
uint256 constant CONTEXT_VAULT_INPUTS_COLUMN = 3;
/// @dev Vault outputs are the same as vault inputs but for the output token from
/// the perspective of the order.
uint256 constant CONTEXT_VAULT_OUTPUTS_COLUMN = 4;

/// @dev Row of the token address for vault inputs and outputs columns.
uint256 constant CONTEXT_VAULT_IO_TOKEN = 0;
/// @dev Row of the token decimals for vault inputs and outputs columns.
uint256 constant CONTEXT_VAULT_IO_TOKEN_DECIMALS = 1;
/// @dev Row of the vault ID for vault inputs and outputs columns.
uint256 constant CONTEXT_VAULT_IO_VAULT_ID = 2;
/// @dev Row of the vault balance before the order was cleared for vault inputs
/// and outputs columns.
uint256 constant CONTEXT_VAULT_IO_BALANCE_BEFORE = 3;
/// @dev Row of the vault balance difference after the order was cleared for
/// vault inputs and outputs columns. The diff is ALWAYS POSITIVE as it is a
/// `uint256` so it must be added to input balances and subtraced from output
/// balances.
uint256 constant CONTEXT_VAULT_IO_BALANCE_DIFF = 4;
/// @dev Length of a vault IO column.
uint256 constant CONTEXT_VAULT_IO_ROWS = 5;

uint256 constant CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN = 5;
uint256 constant CONTEXT_SIGNED_CONTEXT_SIGNERS_ROWS = 1;
uint256 constant CONTEXT_SIGNED_CONTEXT_SIGNERS_ROW = 0;

uint256 constant CONTEXT_SIGNED_CONTEXT_START_COLUMN = 6;
uint256 constant CONTEXT_SIGNED_CONTEXT_START_ROWS = 1;
uint256 constant CONTEXT_SIGNED_CONTEXT_START_ROW = 0;

library LibOrderBook {
    function doPost(uint256[][] memory context, TaskV1[] memory post) internal {
        StateNamespace namespace = StateNamespace.wrap(uint256(uint160(msg.sender)));
        TaskV1 memory task;
        for (uint256 i = 0; i < post.length; ++i) {
            task = post[i];
            if (task.evaluable.bytecode.length > 0) {
                (uint256[] memory stack, uint256[] memory writes) = task.evaluable.interpreter.eval3(
                    task.evaluable.store,
                    LibNamespace.qualifyNamespace(namespace, address(this)),
                    task.evaluable.bytecode,
                    SourceIndexV2.wrap(0),
                    LibContext.build(context, task.signedContext),
                    new uint256[](0)
                );
                (stack);
                if (writes.length > 0) {
                    task.evaluable.store.set(namespace, writes);
                }
            }
        }
    }
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.19;

import {TaskV1} from "rain.orderbook.interface/interface/IOrderBookV4.sol";
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {LibOrderBook} from "./LibOrderBook.sol";
import {Address} from "openzeppelin-contracts/contracts/utils/Address.sol";
import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import {LibFixedPointDecimalScale} from "rain.math.fixedpoint/lib/LibFixedPointDecimalScale.sol";
import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";

/// Thrown when the stack is not empty after the access control dispatch.
error NonZeroBeforeArbStack();

/// Thrown when the lender is not the trusted `OrderBook`.
/// @param badLender The untrusted lender calling `onFlashLoan`.
error BadLender(address badLender);

library LibOrderBookArb {
    using SafeERC20 for IERC20;

    function finalizeArb(TaskV1 memory task, address ordersInputToken, address ordersOutputToken) internal {
        uint256[][] memory context = new uint256[][](1);
        uint256[] memory col = new uint256[](3);

        {
            // Send all unspent input tokens to the sender.
            uint256 inputBalance = IERC20(ordersInputToken).balanceOf(address(this));
            if (inputBalance > 0) {
                IERC20(ordersInputToken).safeTransfer(msg.sender, inputBalance);
            }
            uint256 inputDecimals = IERC20Metadata(ordersInputToken).decimals();
            col[0] = LibFixedPointDecimalScale.scale18(
                inputBalance,
                inputDecimals,
                // Error on overflow.
                // Rounding down is the default.
                0
            );
        }

        {
            // Send all unspent output tokens to the sender.
            uint256 outputBalance = IERC20(ordersOutputToken).balanceOf(address(this));
            if (outputBalance > 0) {
                IERC20(ordersOutputToken).safeTransfer(msg.sender, outputBalance);
            }

            uint256 outputDecimals = IERC20Metadata(ordersOutputToken).decimals();
            col[1] = LibFixedPointDecimalScale.scale18(
                outputBalance,
                outputDecimals,
                // Error on overflow.
                // Rounding down is the default.
                0
            );
        }

        {
            // Send any remaining gas to the sender.
            // Slither false positive here. We want to send everything to the sender
            // because this contract should be empty of all gas and tokens between
            // uses. Anyone who sends tokens or gas to an arb contract without
            // calling `arb` is going to lose their tokens/gas.
            // See https://github.com/crytic/slither/issues/1658
            uint256 gasBalance = address(this).balance;
            Address.sendValue(payable(msg.sender), gasBalance);
            col[2] = gasBalance;
        }

        context[0] = col;

        TaskV1[] memory post = new TaskV1[](1);
        post[0] = task;
        LibOrderBook.doPost(context, post);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {EncodedDispatch, StateNamespace, Operand, DEFAULT_STATE_NAMESPACE} from "./IInterpreterV1.sol";
import {FullyQualifiedNamespace, IInterpreterStoreV2} from "../IInterpreterStoreV2.sol";

/// @dev For maximum compatibility with external contracts, the `IInterpreterV2`
/// should implement an opcode that reads from the stack by index as opcode `0`.
uint256 constant OPCODE_STACK = 0;

/// @dev For maximum compatibility with external contracts, the `IInterpreterV2`
/// should implement an opcode that reads constants by index as opcode `1`.
uint256 constant OPCODE_CONSTANT = 1;

/// @dev For maximum compatibility with external contracts, the `IInterpreterV2`
/// should implement an opcode that calls externs by index as opcode `2`.
uint256 constant OPCODE_EXTERN = 2;

/// @dev For maximum compatibility with external contracts, the `IInterpreterV2`
/// should implement an opcode that reads from the context grid as <column row>
/// as opcode `3`.
uint256 constant OPCODE_CONTEXT = 3;

/// @dev For maximum compatibility with opcode lists, the `IInterpreterV2`
/// should implement the opcode for locally unknown words that need sub parsing
/// as opcode `255`.
uint256 constant OPCODE_UNKNOWN = 0xFF;

/// @dev The index of a source within a deployed expression that can be evaluated
/// by an `IInterpreterV2`. MAY be an entrypoint or the index of a source called
/// internally such as by the `call` opcode.
type SourceIndexV2 is uint256;

/// @title IInterpreterV2
/// Interface into a standard interpreter that supports:
///
/// - evaluating `view` logic deployed onchain by an `IExpressionDeployerV1`
/// - receiving arbitrary `uint256[][]` supporting context to be made available
///   to the evaluated logic
/// - handling subsequent state changes in bulk in response to evaluated logic
/// - namespacing state changes according to the caller's preferences to avoid
///   unwanted key collisions
/// - exposing its internal function pointers to support external precompilation
///   of logic for more gas efficient runtime evaluation by the interpreter
///
/// The interface is designed to be stable across many versions and
/// implementations of an interpreter, balancing minimalism with features
/// required for a general purpose onchain interpreted compute environment.
///
/// The security model of an interpreter is that it MUST be resilient to
/// malicious expressions even if they dispatch arbitrary internal function
/// pointers during an eval. The interpreter MAY return garbage or exhibit
/// undefined behaviour or error during an eval, _provided that no state changes
/// are persisted_ e.g. in storage, such that only the caller that specifies the
/// malicious expression can be negatively impacted by the result. In turn, the
/// caller must guard itself against arbitrarily corrupt/malicious reverts and
/// return values from any interpreter that it requests an expression from. And
/// so on and so forth up to the externally owned account (EOA) who signs the
/// transaction and agrees to a specific combination of contracts, expressions
/// and interpreters, who can presumably make an informed decision about which
/// ones to trust to get the job done.
///
/// The state changes for an interpreter are expected to be produced by an
/// `eval2` and passed to the `IInterpreterStoreV1` returned by the eval, as-is
/// by the caller, after the caller has had an opportunity to apply their own
/// intermediate logic such as reentrancy defenses against malicious
/// interpreters. The interpreter is free to structure the state changes however
/// it wants but MUST guard against the calling contract corrupting the changes
/// between `eval2` and `set`. For example a store could sandbox storage writes
/// per-caller so that a malicious caller can only damage their own state
/// changes, while honest callers respect, benefit from and are protected by the
/// interpreter store's state change handling.
///
/// The two step eval-state model allows evaluation to be read-only which
/// provides security guarantees for the caller such as no stateful reentrancy,
/// either from the interpreter or some contract interface used by some word,
/// while still allowing for storage writes. As the storage writes happen on the
/// interpreter rather than the caller (c.f. delegate call) the caller DOES NOT
/// need to trust the interpreter, which allows for permissionless selection of
/// interpreters by end users. Delegate call always implies an admin key on the
/// caller because the delegatee contract can write arbitrarily to the state of
/// the delegator, which severely limits the generality of contract composition.
interface IInterpreterV2 {
    /// Exposes the function pointers as `uint16` values packed into a single
    /// `bytes` in the same order as they would be indexed into by opcodes. For
    /// example, if opcode `2` should dispatch function at position `0x1234` then
    /// the start of the returned bytes would be `0xXXXXXXXX1234` where `X` is
    /// a placeholder for the function pointers of opcodes `0` and `1`.
    ///
    /// `IExpressionDeployerV3` contracts use these function pointers to
    /// "compile" the expression into something that an interpreter can dispatch
    /// directly without paying gas to lookup the same at runtime. As the
    /// validity of any integrity check and subsequent dispatch is highly
    /// sensitive to both the function pointers and overall bytecode of the
    /// interpreter, `IExpressionDeployerV3` contracts SHOULD implement guards
    /// against accidentally being deployed onchain paired against an unknown
    /// interpreter. It is very easy for an apparent compatible pairing to be
    /// subtly and critically incompatible due to addition/removal/reordering of
    /// opcodes and compiler optimisations on the interpreter bytecode.
    ///
    /// This MAY return different values during construction vs. all other times
    /// after the interpreter has been successfully deployed onchain. DO NOT rely
    /// on function pointers reported during contract construction.
    function functionPointers() external view returns (bytes calldata);

    /// The raison d'etre for an interpreter. Given some expression and per-call
    /// additional contextual data, produce a stack of results and a set of state
    /// changes that the caller MAY OPTIONALLY pass back to be persisted by a
    /// call to `IInterpreterStoreV1.set`.
    ///
    /// There are two key differences between `eval` and `eval2`:
    /// - `eval` was ambiguous about whether the top value of the final stack is
    /// the first or last item of the array. `eval2` is unambiguous in that the
    /// top of the stack MUST be the first item in the array.
    /// - `eval2` allows the caller to specify inputs to the entrypoint stack of
    /// the expression. This allows the `eval` and `offchainDebugEval` functions
    /// to be merged into a single function that can be used for both onchain and
    /// offchain evaluation. For example, the caller can simulate "internal"
    /// calls by specifying the inputs to the entrypoint stack of the expression
    /// as the outputs of some other expression. Legacy behaviour can be achieved
    /// by passing an empty array for `inputs`.
    ///
    /// @param store The storage contract that the returned key/value pairs
    /// MUST be passed to IF the calling contract is in a non-static calling
    /// context. Static calling contexts MUST pass `address(0)`.
    /// @param namespace The fully qualified namespace that will be used by the
    /// interpreter at runtime in order to perform gets on the underlying store.
    /// @param dispatch All the information required for the interpreter to load
    /// an expression, select an entrypoint and return the values expected by the
    /// caller. The interpreter MAY encode dispatches differently to
    /// `LibEncodedDispatch` but this WILL negatively impact compatibility for
    /// calling contracts that hardcode the encoding logic.
    /// @param context A 2-dimensional array of data that can be indexed into at
    /// runtime by the interpreter. The calling contract is responsible for
    /// ensuring the authenticity and completeness of context data. The
    /// interpreter MUST revert at runtime if an expression attempts to index
    /// into some context value that is not provided by the caller. This implies
    /// that context reads cannot be checked for out of bounds reads at deploy
    /// time, as the runtime context MAY be provided in a different shape to what
    /// the expression is expecting.
    /// @param inputs The inputs to the entrypoint stack of the expression. MAY
    /// be empty if the caller prefers to specify all inputs via. context.
    /// @return stack The list of values produced by evaluating the expression.
    /// MUST NOT be longer than the maximum length specified by `dispatch`, if
    /// applicable. MUST be ordered such that the top of the stack is the FIRST
    /// item in the array.
    /// @return writes A list of values to be processed by a store. Most likely
    /// will be pairwise key/value items but this is not strictly required if
    /// some store expects some other format.
    function eval2(
        IInterpreterStoreV2 store,
        FullyQualifiedNamespace namespace,
        EncodedDispatch dispatch,
        uint256[][] calldata context,
        uint256[] calldata inputs
    ) external view returns (uint256[] calldata stack, uint256[] calldata writes);
}

// SPDX-License-Identifier: CC0
// Alberto Cuesta Cañada, Fiona Kobayashi, fubuloubu, Austin Williams, "EIP-3156: Flash Loans," Ethereum Improvement Proposals, no. 3156, November 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-3156.
pragma solidity ^0.8.18;

import {IERC3156FlashBorrower} from "./IERC3156FlashBorrower.sol";

interface IERC3156FlashLender {
    /**
     * @dev The amount of currency available to be lent.
     * @param token The loan currency.
     * @return The amount of `token` that can be borrowed.
     */
    function maxFlashLoan(address token) external view returns (uint256);

    /**
     * @dev The fee to be charged for a given loan.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @return The amount of `token` to be charged for the loan, on top of the returned principal.
     */
    function flashFee(address token, uint256 amount) external view returns (uint256);

    /**
     * @dev Initiate a flash loan.
     * @param receiver The receiver of the tokens in the loan, and the receiver of the callback.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @param data Arbitrary data structure, intended to contain user-defined parameters.
     */
    function flashLoan(IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data)
        external
        returns (bool);
}

File 24 of 55 : IInterpreterCallerV3.sol
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {IParserV2} from "./IParserV2.sol";
import {IInterpreterStoreV2} from "./IInterpreterStoreV2.sol";
import {IInterpreterV3} from "./IInterpreterV3.sol";
import {
    SignedContextV1,
    SIGNED_CONTEXT_SIGNER_OFFSET,
    SIGNED_CONTEXT_CONTEXT_OFFSET,
    SIGNED_CONTEXT_SIGNATURE_OFFSET
} from "./deprecated/IInterpreterCallerV2.sol";

/// Struct over the return of `IParserV2.parse2` which MAY be more convenient to
/// work with than raw addresses.
/// @param interpreter Will evaluate the expression.
/// @param store Will store state changes due to evaluation of the expression.
/// @param expression Will be evaluated by the interpreter.
struct EvaluableV3 {
    IInterpreterV3 interpreter;
    IInterpreterStoreV2 store;
    bytes bytecode;
}

/// @title IInterpreterCallerV3
/// @notice A contract that calls an `IInterpreterV3` via. `eval3`. There are
/// near zero requirements on a caller other than:
///
/// - Provide the context, which can be built in a standard way by `LibContext`
/// - Handle the stack array returned from `eval3`
/// - OPTIONALLY emit the `Context` event
/// - OPTIONALLY set state on the `IInterpreterStoreV2` returned from `eval3`.
interface IInterpreterCallerV3 {
    /// Calling contracts SHOULD emit `Context` before calling `eval3` if they
    /// are able. Notably `eval3` MAY be called within a static call which means
    /// that events cannot be emitted, in which case this does not apply. It MAY
    /// NOT be useful to emit this multiple times for several eval calls if they
    /// all share a common context, in which case a single emit is sufficient.
    /// @param sender `msg.sender` building the context.
    /// @param context The context that was built.
    event Context(address sender, uint256[][] context);
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {IERC3156FlashLender} from "../../ierc3156/IERC3156FlashLender.sol";
import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol";
import {
    EvaluableConfigV3,
    IInterpreterCallerV2,
    SignedContextV1
} from "rain.interpreter.interface/interface/deprecated/IInterpreterCallerV2.sol";
import {IExpressionDeployerV3} from "rain.interpreter.interface/interface/deprecated/IExpressionDeployerV3.sol";

/// Import unmodified structures from older versions of `IOrderBook`.
import {IO, ClearConfig, ClearStateChange} from "../v2/IOrderBookV2.sol";

/// Thrown when take orders is called with no orders.
error NoOrders();

/// Thrown when take orders is called with a zero maximum input.
error ZeroMaximumInput();

/// Config the order owner may provide to define their order. The `msg.sender`
/// that adds an order cannot modify the owner nor bypass the integrity check of
/// the expression deployer that they specify. However they MAY specify a
/// deployer with a corrupt integrity check, so counterparties and clearers MUST
/// check the DISpair of the order and avoid untrusted pairings.
/// @param validInputs As per `validInputs` on the `Order`.
/// @param validOutputs As per `validOutputs` on the `Order`.
/// @param evaluableConfig Standard `EvaluableConfig` used to produce the
/// `Evaluable` on the order.
/// @param meta Arbitrary bytes that will NOT be used in the order evaluation
/// but MUST be emitted as a Rain `MetaV1` when the order is placed so can be
/// used by offchain processes.
struct OrderConfigV2 {
    IO[] validInputs;
    IO[] validOutputs;
    EvaluableConfigV3 evaluableConfig;
    bytes meta;
}

/// Config for an individual take order from the overall list of orders in a
/// call to `takeOrders`.
/// @param order The order being taken this iteration.
/// @param inputIOIndex The index of the input token in `order` to match with the
/// take order output.
/// @param outputIOIndex The index of the output token in `order` to match with
/// the take order input.
/// @param signedContext Optional additional signed context relevant to the
/// taken order.
struct TakeOrderConfigV2 {
    OrderV2 order;
    uint256 inputIOIndex;
    uint256 outputIOIndex;
    SignedContextV1[] signedContext;
}

/// Defines a fully deployed order ready to evaluate by Orderbook. Identical to
/// `Order` except for the newer `EvaluableV2`.
/// @param owner The owner of the order is the `msg.sender` that added the order.
/// @param handleIO true if there is a "handle IO" entrypoint to run. If false
/// the order book MAY skip calling the interpreter to save gas.
/// @param evaluable Standard `EvaluableV2` with entrypoints for both
/// "calculate order" and "handle IO". The latter MAY be empty bytes, in which
/// case it will be skipped at runtime to save gas.
/// @param validInputs A list of input tokens that are economically equivalent
/// for the purpose of processing this order. Inputs are relative to the order
/// so these tokens will be sent to the owners vault.
/// @param validOutputs A list of output tokens that are economically equivalent
/// for the purpose of processing this order. Outputs are relative to the order
/// so these tokens will be sent from the owners vault.
struct OrderV2 {
    address owner;
    bool handleIO;
    EvaluableV2 evaluable;
    IO[] validInputs;
    IO[] validOutputs;
}

/// Config for a list of orders to take sequentially as part of a `takeOrders`
/// call.
/// @param minimumInput Minimum input from the perspective of the order taker.
/// @param maximumInput Maximum input from the perspective of the order taker.
/// @param maximumIORatio Maximum IO ratio as calculated by the order being
/// taken. The input is from the perspective of the order so higher ratio means
/// worse deal for the order taker.
/// @param orders Ordered list of orders that will be taken until the limit is
/// hit. Takers are expected to prioritise orders that appear to be offering
/// better deals i.e. lower IO ratios. This prioritisation and sorting MUST
/// happen offchain, e.g. via. some simulator.
/// @param data If nonzero length, triggers `onTakeOrders` on the caller of
/// `takeOrders` with this data. This allows the caller to perform arbitrary
/// onchain actions between receiving their input tokens, before having to send
/// their output tokens.
struct TakeOrdersConfigV2 {
    uint256 minimumInput;
    uint256 maximumInput;
    uint256 maximumIORatio;
    TakeOrderConfigV2[] orders;
    bytes data;
}

/// @title IOrderBookV3
/// @notice An orderbook that deploys _strategies_ represented as interpreter
/// expressions rather than individual orders. The order book contract itself
/// behaves similarly to an `ERC4626` vault but with much more fine grained
/// control over how tokens are allocated and moved internally by their owners,
/// and without any concept of "shares". Token owners MAY deposit and withdraw
/// their tokens under arbitrary vault IDs on a per-token basis, then define
/// orders that specify how tokens move between vaults according to an expression.
/// The expression returns a maximum amount and a token input/output ratio from
/// the perpective of the order. When two expressions intersect, as in their
/// ratios are the inverse of each other, then tokens can move between vaults.
///
/// For example, consider order A with input TKNA and output TKNB with a constant
/// ratio of 100:1. This order in isolation has no ability to move tokens. If
/// an order B appears with input TKNB and output TKNA and a ratio of 1:100 then
/// this is a perfect match with order A. In this case 100 TKNA will move from
/// order B to order A and 1 TKNB will move from order A to order B.
///
/// IO ratios are always specified as input:output and are 18 decimal fixed point
/// values. The maximum amount that can be moved in the current clearance is also
/// set by the order expression as an 18 decimal fixed point value.
///
/// Typically orders will not clear when their match is exactly 1:1 as the
/// clearer needs to pay gas to process the match. Each order will get exactly
/// the ratio it calculates when it does clear so if there is _overlap_ in the
/// ratios then the clearer keeps the difference. In our above example, consider
/// order B asking a ratio of 1:110 instead of 1:100. In this case 100 TKNA will
/// move from order B to order A and 10 TKNA will move to the clearer's vault and
/// 1 TKNB will move from order A to order B. In the case of fixed prices this is
/// not very interesting as order B could more simply take order A directly for
/// cheaper rather than involving a third party. Indeed, Orderbook supports a
/// direct "take orders" method that works similar to a "market buy". In the case
/// of dynamic expression based ratios, it allows both order A and order B to
/// clear non-interactively according to their strategy, trading off active
/// management, dealing with front-running, MEV, etc. for zero-gas and
/// exact-ratio clearance.
///
/// The general invariant for clearing and take orders is:
///
/// ```
/// ratioA = InputA / OutputA
/// ratioB = InputB / OutputB
/// ratioA * ratioB = ( InputA * InputB ) / ( OutputA * OutputB )
/// OutputA >= InputB
/// OutputB >= InputA
///
/// ∴ ratioA * ratioB <= 1
/// ```
///
/// Orderbook is `IERC3156FlashLender` compliant with a 0 fee flash loan
/// implementation to allow external liquidity from other onchain DEXes to match
/// against orderbook expressions. All deposited tokens across all vaults are
/// available for flashloan, the flashloan MAY BE REPAID BY CALLING TAKE ORDER
/// such that Orderbook's liability to its vaults is decreased by an incoming
/// trade from the flashloan borrower. See `ZeroExOrderBookFlashBorrower` for
/// an example of how this works in practise.
///
/// Orderbook supports many to many input/output token relationship, for example
/// some order can specify an array of stables it would be willing to accept in
/// return for some ETH. This removes the need for a combinatorial explosion of
/// order strategies between like assets but introduces the issue of token
/// decimal handling. End users understand that "one" USDT is roughly equal to
/// "one" DAI, but onchain this is incorrect by _12 orders of magnitude_. This
/// is because "one" DAI is `1e18` tokens and "one" USDT is `1e6` tokens. The
/// orderbook is allowing orders to deploy expressions that define _economic
/// equivalence_ but this doesn't map 1:1 with numeric equivalence in a many to
/// many setup behind token decimal convensions. The solution is to require that
/// end users who place orders provide the decimals of each token they include
/// in their valid IO lists, and to calculate all amounts and ratios in their
/// expressions _as though they were 18 decimal fixed point values_. Orderbook
/// will then automatically rescale the expression values before applying the
/// final vault movements. If an order provides the "wrong" decimal values for
/// some token then it will simply calculate its own ratios and amounts
/// incorrectly which will either lead to no matching orders or a very bad trade
/// for the order owner. There is no way that misrepresenting decimals can attack
/// some other order by a counterparty. Orderbook DOES NOT read decimals from
/// tokens onchain because A. this would be gas for an external call to a cold
/// token contract and B. the ERC20 standard specifically states NOT to read
/// decimals from the interface onchain.
///
/// Token amounts and ratios returned by calculate order MUST be 18 decimal fixed
/// point values. Token amounts input to handle IO MUST be the exact absolute
/// values that move between the vaults, i.e. NOT rescaled to 18 decimals. The
/// author of the handle IO expression MUST use the token decimals and amounts to
/// rescale themselves if they want that logic, notably the expression author
/// will need to specify the desired rounding behaviour in the rescaling process.
///
/// When two orders clear there are NO TOKEN MOVEMENTS, only internal vault
/// balances are updated from the input and output vaults. Typically this results
/// in less gas per clear than calling external token transfers and also avoids
/// issues with reentrancy, allowances, external balances etc. This also means
/// that REBASING TOKENS AND TOKENS WITH DYNAMIC BALANCE ARE NOT SUPPORTED.
/// Orderbook ONLY WORKS IF TOKEN BALANCES ARE 1:1 WITH ADDITION/SUBTRACTION PER
/// VAULT MOVEMENT.
///
/// Dust due to rounding errors always favours the order. Output max is rounded
/// down and IO ratios are rounded up. Input and output amounts are always
/// converted to absolute values before applying to vault balances such that
/// orderbook always retains fully collateralised inventory of underlying token
/// balances to support withdrawals, with the caveat that dynamic token balanes
/// are not supported.
///
/// When an order clears it is NOT removed. Orders remain active until the owner
/// deactivates them. This is gas efficient as order owners MAY deposit more
/// tokens in a vault with an order against it many times and the order strategy
/// will continue to be clearable according to its expression. As vault IDs are
/// `uint256` values there are effectively infinite possible vaults for any token
/// so there is no limit to how many active orders any address can have at one
/// time. This also allows orders to be daisy chained arbitrarily where output
/// vaults for some order are the input vaults for some other order.
///
/// Expression storage is namespaced by order owner, so gets and sets are unique
/// to each onchain address. Order owners MUST TAKE CARE not to override their
/// storage sets globally across all their orders, which they can do most simply
/// by hashing the order hash into their get/set keys inside the expression. This
/// gives maximum flexibility for shared state across orders without allowing
/// order owners to attack and overwrite values stored by orders placed by their
/// counterparty.
///
/// Note that each order specifies its own interpreter and deployer so the
/// owner is responsible for not corrupting their own calculations with bad
/// interpreters. This also means the Orderbook MUST assume the interpreter, and
/// notably the interpreter's store, is malicious and guard against reentrancy
/// etc.
///
/// As Orderbook supports any expression that can run on any `IInterpreterV1` and
/// counterparties are available to the order, order strategies are free to
/// implement KYC/membership, tracking, distributions, stock, buybacks, etc. etc.
///
/// Main differences between `IOrderBookV2` and `IOderBookV3`:
/// - Most structs are now primitives to save gas.
/// - Order hash is `bytes32`.
/// - `deposit` and `withdraw` MUST revert if the amount is zero.
/// - adding an order MUST revert if there is no calculation entrypoint.
/// - adding an order MUST revert if there is no handle IO entrypoint.
/// - adding an order MUST revert if there are no inputs.
/// - adding an order MUST revert if there are no outputs.
/// - adding and removing orders MUST return a boolean indicating if the state
/// changed.
/// - new `orderExists` method.
interface IOrderBookV3 is IERC3156FlashLender, IInterpreterCallerV2 {
    /// MUST be thrown by `deposit` if the amount is zero.
    /// @param sender `msg.sender` depositing tokens.
    /// @param token The token being deposited.
    /// @param vaultId The vault ID the tokens are being deposited under.
    error ZeroDepositAmount(address sender, address token, uint256 vaultId);

    /// MUST be thrown by `withdraw` if the amount _requested_ to withdraw is
    /// zero. The withdrawal MAY still not move any tokens if the vault balance
    /// is zero, or the withdrawal is used to repay a flash loan.
    /// @param sender `msg.sender` withdrawing tokens.
    /// @param token The token being withdrawn.
    /// @param vaultId The vault ID the tokens are being withdrawn from.
    error ZeroWithdrawTargetAmount(address sender, address token, uint256 vaultId);

    /// MUST be thrown by `addOrder` if the order has no associated calculation.
    error OrderNoSources();

    /// MUST be thrown by `addOrder` if the order has no associated handle IO.
    error OrderNoHandleIO();

    /// MUST be thrown by `addOrder` if the order has no inputs.
    error OrderNoInputs();

    /// MUST be thrown by `addOrder` if the order has no outputs.
    error OrderNoOutputs();

    /// Some tokens have been deposited to a vault.
    /// @param sender `msg.sender` depositing tokens. Delegated deposits are NOT
    /// supported.
    /// @param token The token being deposited.
    /// @param vaultId The vault ID the tokens are being deposited under.
    /// @param amount The amount of tokens deposited.
    event Deposit(address sender, address token, uint256 vaultId, uint256 amount);

    /// Some tokens have been withdrawn from a vault.
    /// @param sender `msg.sender` withdrawing tokens. Delegated withdrawals are
    /// NOT supported.
    /// @param token The token being withdrawn.
    /// @param vaultId The vault ID the tokens are being withdrawn from.
    /// @param targetAmount The amount of tokens requested to withdraw.
    /// @param amount The amount of tokens withdrawn, can be less than the
    /// target amount if the vault does not have the funds available to cover
    /// the target amount. For example an active order might move tokens before
    /// the withdraw completes.
    event Withdraw(address sender, address token, uint256 vaultId, uint256 targetAmount, uint256 amount);

    /// An order has been added to the orderbook. The order is permanently and
    /// always active according to its expression until/unless it is removed.
    /// @param sender `msg.sender` adding the order and is owner of the order.
    /// @param expressionDeployer The expression deployer that ran the integrity
    /// check for this order. This is NOT included in the `Order` itself but is
    /// important for offchain processes to ignore untrusted deployers before
    /// interacting with them.
    /// @param order The newly added order. MUST be handed back as-is when
    /// clearing orders and contains derived information in addition to the order
    /// config that was provided by the order owner.
    /// @param orderHash The hash of the order as it is recorded onchain. Only
    /// the hash is stored in Orderbook storage to avoid paying gas to store the
    /// entire order.
    event AddOrder(address sender, IExpressionDeployerV3 expressionDeployer, OrderV2 order, bytes32 orderHash);

    /// An order has been removed from the orderbook. This effectively
    /// deactivates it. Orders can be added again after removal.
    /// @param sender `msg.sender` removing the order and is owner of the order.
    /// @param order The removed order.
    /// @param orderHash The hash of the removed order.
    event RemoveOrder(address sender, OrderV2 order, bytes32 orderHash);

    /// Some order has been taken by `msg.sender`. This is the same as them
    /// placing inverse orders then immediately clearing them all, but costs less
    /// gas and is more convenient and reliable. Analogous to a market buy
    /// against the specified orders. Each order that is matched within a the
    /// `takeOrders` loop emits its own individual event.
    /// @param sender `msg.sender` taking the orders.
    /// @param config All config defining the orders to attempt to take.
    /// @param input The input amount from the perspective of sender.
    /// @param output The output amount from the perspective of sender.
    event TakeOrder(address sender, TakeOrderConfigV2 config, uint256 input, uint256 output);

    /// Emitted when attempting to match an order that either never existed or
    /// was removed. An event rather than an error so that we allow attempting
    /// many orders in a loop and NOT rollback on "best effort" basis to clear.
    /// @param sender `msg.sender` clearing the order that wasn't found.
    /// @param owner Owner of the order that was not found.
    /// @param orderHash Hash of the order that was not found.
    event OrderNotFound(address sender, address owner, bytes32 orderHash);

    /// Emitted when an order evaluates to a zero amount. An event rather than an
    /// error so that we allow attempting many orders in a loop and NOT rollback
    /// on a "best effort" basis to clear.
    /// @param sender `msg.sender` clearing the order that had a 0 amount.
    /// @param owner Owner of the order that evaluated to a 0 amount.
    /// @param orderHash Hash of the order that evaluated to a 0 amount.
    event OrderZeroAmount(address sender, address owner, bytes32 orderHash);

    /// Emitted when an order evaluates to a ratio exceeding the counterparty's
    /// maximum limit. An error rather than an error so that we allow attempting
    /// many orders in a loop and NOT rollback on a "best effort" basis to clear.
    /// @param sender `msg.sender` clearing the order that had an excess ratio.
    /// @param owner Owner of the order that had an excess ratio.
    /// @param orderHash Hash of the order that had an excess ratio.
    event OrderExceedsMaxRatio(address sender, address owner, bytes32 orderHash);

    /// Emitted before two orders clear. Covers both orders and includes all the
    /// state before anything is calculated.
    /// @param sender `msg.sender` clearing both orders.
    /// @param alice One of the orders.
    /// @param bob The other order.
    /// @param clearConfig Additional config required to process the clearance.
    event Clear(address sender, OrderV2 alice, OrderV2 bob, ClearConfig clearConfig);

    /// Emitted after two orders clear. Includes all final state changes in the
    /// vault balances, including the clearer's vaults.
    /// @param sender `msg.sender` clearing the order.
    /// @param clearStateChange The final vault state changes from the clearance.
    event AfterClear(address sender, ClearStateChange clearStateChange);

    /// Get the current balance of a vault for a given owner, token and vault ID.
    /// @param owner The owner of the vault.
    /// @param token The token the vault is for.
    /// @param id The vault ID to read.
    /// @return balance The current balance of the vault.
    function vaultBalance(address owner, address token, uint256 id) external view returns (uint256 balance);

    /// `msg.sender` deposits tokens according to config. The config specifies
    /// the vault to deposit tokens under. Delegated depositing is NOT supported.
    /// Depositing DOES NOT mint shares (unlike ERC4626) so the overall vaulted
    /// experience is much simpler as there is always a 1:1 relationship between
    /// deposited assets and vault balances globally and individually. This
    /// mitigates rounding/dust issues, speculative behaviour on derived assets,
    /// possible regulatory issues re: whether a vault share is a security, code
    /// bloat on the vault, complex mint/deposit/withdraw/redeem 4-way logic,
    /// the need for preview functions, etc. etc.
    ///
    /// At the same time, allowing vault IDs to be specified by the depositor
    /// allows much more granular and direct control over token movements within
    /// Orderbook than either ERC4626 vault shares or mere contract-level ERC20
    /// allowances can facilitate.
    //
    /// Vault IDs are namespaced by the token address so there is no risk of
    /// collision between tokens. For example, vault ID 0 for token A is
    /// completely different to vault ID 0 for token B.
    ///
    /// `0` amount deposits are unsupported as underlying token contracts
    /// handle `0` value transfers differently and this would be a source of
    /// confusion. The order book MUST revert with `ZeroDepositAmount` if the
    /// amount is zero.
    ///
    /// @param token The token to deposit.
    /// @param vaultId The vault ID to deposit under.
    /// @param amount The amount of tokens to deposit.
    function deposit(address token, uint256 vaultId, uint256 amount) external;

    /// Allows the sender to withdraw any tokens from their own vaults. If the
    /// withrawer has an active flash loan debt denominated in the same token
    /// being withdrawn then Orderbook will merely reduce the debt and NOT send
    /// the amount of tokens repaid to the flashloan debt.
    ///
    /// MUST revert if the amount _requested_ to withdraw is zero. The withdrawal
    /// MAY still not move any tokens (without revert) if the vault balance is
    /// zero, or the withdrawal is used to repay a flash loan, or due to any
    /// other internal accounting.
    ///
    /// @param token The token to withdraw.
    /// @param vaultId The vault ID to withdraw from.
    /// @param targetAmount The amount of tokens to attempt to withdraw. MAY
    /// result in fewer tokens withdrawn if the vault balance is lower than the
    /// target amount. MAY NOT be zero, the order book MUST revert with
    /// `ZeroWithdrawTargetAmount` if the amount is zero.
    function withdraw(address token, uint256 vaultId, uint256 targetAmount) external;

    /// Given an order config, deploys the expression and builds the full `Order`
    /// for the config, then records it as an active order. Delegated adding an
    /// order is NOT supported. The `msg.sender` that adds an order is ALWAYS
    /// the owner and all resulting vault movements are their own.
    ///
    /// MUST revert with `OrderNoSources` if the order has no associated
    /// calculation and `OrderNoHandleIO` if the order has no handle IO
    /// entrypoint. The calculation MUST return at least two values from
    /// evaluation, the maximum amount and the IO ratio. The handle IO entrypoint
    /// SHOULD return zero values from evaluation. Either MAY revert during
    /// evaluation on the interpreter, which MUST prevent the order from
    /// clearing.
    ///
    /// MUST revert with `OrderNoInputs` if the order has no inputs.
    /// MUST revert with `OrderNoOutputs` if the order has no outputs.
    ///
    /// If the order already exists, the order book MUST NOT change state, which
    /// includes not emitting an event. Instead it MUST return false. If the
    /// order book modifies state it MUST emit an `AddOrder` event and return
    /// true.
    ///
    /// @param config All config required to build an `Order`.
    /// @return stateChanged True if the order was added, false if it already
    /// existed.
    function addOrder(OrderConfigV2 calldata config) external returns (bool stateChanged);

    /// Returns true if the order exists, false otherwise.
    /// @param orderHash The hash of the order to check.
    /// @return exists True if the order exists, false otherwise.
    function orderExists(bytes32 orderHash) external view returns (bool exists);

    /// Order owner can remove their own orders. Delegated order removal is NOT
    /// supported and will revert. Removing an order multiple times or removing
    /// an order that never existed are valid, the event will be emitted and the
    /// transaction will complete with that order hash definitely, redundantly
    /// not live.
    /// @param order The `Order` data exactly as it was added.
    /// @return stateChanged True if the order was removed, false if it did not
    /// exist.
    function removeOrder(OrderV2 calldata order) external returns (bool stateChanged);

    /// Allows `msg.sender` to attempt to fill a list of orders in sequence
    /// without needing to place their own order and clear them. This works like
    /// a market buy but against a specific set of orders. Every order will
    /// looped over and calculated individually then filled maximally until the
    /// request input is reached for the `msg.sender`. The `msg.sender` is
    /// responsible for selecting the best orders at the time according to their
    /// criteria and MAY specify a maximum IO ratio to guard against an order
    /// spiking the ratio beyond what the `msg.sender` expected and is
    /// comfortable with. As orders may be removed and calculate their ratios
    /// dynamically, all issues fulfilling an order other than misconfiguration
    /// by the `msg.sender` are no-ops and DO NOT revert the transaction. This
    /// allows the `msg.sender` to optimistically provide a list of orders that
    /// they aren't sure will completely fill at a good price, and fallback to
    /// more reliable orders further down their list. Misconfiguration such as
    /// token mismatches are errors that revert as this is known and static at
    /// all times to the `msg.sender` so MUST be provided correctly. `msg.sender`
    /// MAY specify a minimum input that MUST be reached across all orders in the
    /// list, otherwise the transaction will revert, this MAY be set to zero.
    ///
    /// Exactly like withdraw, if there is an active flash loan for `msg.sender`
    /// they will have their outstanding loan reduced by the final input amount
    /// preferentially before sending any tokens. Notably this allows arb bots
    /// implemented as flash loan borrowers to connect orders against external
    /// liquidity directly by paying back the loan with a `takeOrders` call and
    /// outputting the result of the external trade.
    ///
    /// Rounding errors always favour the order never the `msg.sender`.
    ///
    /// @param config The constraints and list of orders to take, orders are
    /// processed sequentially in order as provided, there is NO ATTEMPT onchain
    /// to predict/filter/sort these orders other than evaluating them as
    /// provided. Inputs and outputs are from the perspective of `msg.sender`
    /// except for values specified by the orders themselves which are the from
    /// the perspective of that order.
    /// @return totalInput Total tokens sent to `msg.sender`, taken from order
    /// vaults processed.
    /// @return totalOutput Total tokens taken from `msg.sender` and distributed
    /// between vaults.
    function takeOrders(TakeOrdersConfigV2 calldata config)
        external
        returns (uint256 totalInput, uint256 totalOutput);

    /// Allows `msg.sender` to match two live orders placed earlier by
    /// non-interactive parties and claim a bounty in the process. The clearer is
    /// free to select any two live orders on the order book for matching and as
    /// long as they have compatible tokens, ratios and amounts, the orders will
    /// clear. Clearing the orders DOES NOT remove them from the orderbook, they
    /// remain live until explicitly removed by their owner. Even if the input
    /// vault balances are completely emptied, the orders remain live until
    /// removed. This allows order owners to deploy a strategy over a long period
    /// of time and periodically top up the input vaults. Clearing two orders
    /// from the same owner is disallowed.
    ///
    /// Any mismatch in the ratios between the two orders will cause either more
    /// inputs than there are available outputs (transaction will revert) or less
    /// inputs than there are available outputs. In the latter case the excess
    /// outputs are given to the `msg.sender` of clear, to the vaults they
    /// specify in the clear config. This not only incentivises "automatic" clear
    /// calls for both alice and bob, but incentivises _prioritising greater
    /// ratio differences_ with a larger bounty. The second point is important
    /// because it implicitly prioritises orders that are further from the
    /// current market price, thus putting constant increasing pressure on the
    /// entire system the further it drifts from the norm, no matter how esoteric
    /// the individual order expressions and sizings might be.
    ///
    /// All else equal there are several factors that would impact how reliably
    /// some order clears relative to the wider market, such as:
    ///
    /// - Bounties are effectively percentages of cleared amounts so larger
    ///   orders have larger bounties and cover gas costs more easily
    /// - High gas on the network means that orders are harder to clear
    ///   profitably so the negative spread of the ratios will need to be larger
    /// - Complex and stateful expressions cost more gas to evalulate so the
    ///   negative spread will need to be larger
    /// - Erratic behavior of the order owner could reduce the willingness of
    ///   third parties to interact if it could result in wasted gas due to
    ///   orders suddently being removed before clearance etc.
    /// - Dynamic and highly volatile words used in the expression could be
    ///   ignored or low priority by clearers who want to be sure that they can
    ///   accurately predict the ratios that they include in their clearance
    /// - Geopolitical issues such as sanctions and regulatory restrictions could
    ///   cause issues for certain owners and clearers
    ///
    /// @param alice Some order to clear.
    /// @param bob Another order to clear.
    /// @param clearConfig Additional configuration for the clearance such as
    /// how to handle the bounty payment for the `msg.sender`.
    /// @param aliceSignedContext Optional signed context that is relevant to A.
    /// @param bobSignedContext Optional signed context that is relevant to B.
    function clear(
        OrderV2 memory alice,
        OrderV2 memory bob,
        ClearConfig calldata clearConfig,
        SignedContextV1[] memory aliceSignedContext,
        SignedContextV1[] memory bobSignedContext
    ) external;
}

File 26 of 55 : IOrderBookV4OrderTaker.sol
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

interface IOrderBookV4OrderTaker {
    /// @notice Called by `IOrderBookV4` when `takeOrders` is called with
    /// non-zero data, if it caused a non-zero input amount. I.e. if the order(s)
    /// taker received some tokens. Input and output directions are relative to
    /// the `IOrderBookV4OrderTaker` contract. If the order(s) taker had an
    /// active debt from a flash loan then that debt will be paid _before_
    /// calculating any input amounts sent.
    /// i.e. the debt is deducted from the input amount before this callback is
    /// called.
    /// @param inputToken The token that was sent to `IOrderBookV4OrderTaker`.
    /// @param outputToken The token that `IOrderBookV4` will attempt to pull
    /// from `IOrderBookV4OrderTaker` after this callback returns.
    /// @param inputAmountSent The amount of `inputToken` that was sent to
    /// `IOrderBookV4OrderTaker`.
    /// @param totalOutputAmount The total amount of `outputToken` that
    /// `IOrderBookV4` will attempt to pull from `IOrderBookV4OrderTaker` after
    /// this callback returns.
    /// @param takeOrdersData The data passed to `takeOrders` by the caller.
    function onTakeOrders(
        address inputToken,
        address outputToken,
        uint256 inputAmountSent,
        uint256 totalOutputAmount,
        bytes calldata takeOrdersData
    ) external;
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {StateNamespace} from "./IInterpreterV1.sol";

/// A fully qualified namespace includes the interpreter's own namespacing logic
/// IN ADDITION to the calling contract's requested `StateNamespace`. Typically
/// this involves hashing the `msg.sender` into the `StateNamespace` so that each
/// caller operates within its own disjoint state universe. Intepreters MUST NOT
/// allow either the caller nor any expression/word to modify this directly on
/// pain of potential key collisions on writes to the interpreter's own storage.
type FullyQualifiedNamespace is uint256;

IInterpreterStoreV1 constant NO_STORE = IInterpreterStoreV1(address(0));

/// @title IInterpreterStoreV1
/// @notice Tracks state changes on behalf of an interpreter. A single store can
/// handle state changes for many calling contracts, many interpreters and many
/// expressions. The store is responsible for ensuring that applying these state
/// changes is safe from key collisions with calls to `set` from different
/// `msg.sender` callers. I.e. it MUST NOT be possible for a caller to modify the
/// state changes associated with some other caller.
///
/// The store defines the shape of its own state changes, which is opaque to the
/// calling contract. For example, some store may treat the list of state changes
/// as a pairwise key/value set, and some other store may treat it as a literal
/// list to be stored as-is.
///
/// Each interpreter decides for itself which store to use based on the
/// compatibility of its own opcodes.
///
/// The store MUST assume the state changes have been corrupted by the calling
/// contract due to bugs or malicious intent, and enforce state isolation between
/// callers despite arbitrarily invalid state changes. The store MUST revert if
/// it can detect invalid state changes, such as a key/value list having an odd
/// number of items, but this MAY NOT be possible if the corruption is
/// undetectable.
interface IInterpreterStoreV1 {
    /// Mutates the interpreter store in bulk. The bulk values are provided in
    /// the form of a `uint256[]` which can be treated e.g. as pairwise keys and
    /// values to be stored in a Solidity mapping. The `IInterpreterStoreV1`
    /// defines the meaning of the `uint256[]` for its own storage logic.
    ///
    /// @param namespace The unqualified namespace for the set that MUST be
    /// fully qualified by the `IInterpreterStoreV1` to prevent key collisions
    /// between callers. The fully qualified namespace forms a compound key with
    /// the keys for each value to set.
    /// @param kvs The list of changes to apply to the store's internal state.
    function set(StateNamespace namespace, uint256[] calldata kvs) external;

    /// Given a fully qualified namespace and key, return the associated value.
    /// Ostensibly the interpreter can use this to implement opcodes that read
    /// previously set values. The interpreter MUST apply the same qualification
    /// logic as the store that it uses to guarantee consistent round tripping of
    /// data and prevent malicious behaviours. Technically also allows onchain
    /// reads of any set value from any contract, not just interpreters, but in
    /// this case readers MUST be aware and handle inconsistencies between get
    /// and set while the state changes are still in memory in the calling
    /// context and haven't yet been persisted to the store.
    ///
    /// `IInterpreterStoreV1` uses the same fallback behaviour for unset keys as
    /// Solidity. Specifically, any UNSET VALUES SILENTLY FALLBACK TO `0`.
    /// @param namespace The fully qualified namespace to get a single value for.
    /// @param key The key to get the value for within the namespace.
    /// @return The value OR ZERO IF NOT SET.
    function get(FullyQualifiedNamespace namespace, uint256 key) external view returns (uint256);
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

/// Export dispair interfaces for convenience downstream.
import {IInterpreterStoreV2} from "../../interface/IInterpreterStoreV2.sol";
import {IInterpreterV2} from "../../interface/deprecated/IInterpreterV2.sol";
import {EvaluableV2} from "../../interface/deprecated/IInterpreterCallerV2.sol";

import {EvaluableV3} from "../../interface/IInterpreterCallerV3.sol";

/// @title LibEvaluable
/// @notice Common logic to provide consistent implementations of common tasks
/// that could be arbitrarily/ambiguously implemented, but work much better if
/// consistently implemented.
library LibEvaluable {
    /// Hashes an `EvaluableV2`, ostensibly so that only the hash need be stored,
    /// thus only storing a single `uint256` instead of 3x `uint160`.
    /// @param evaluable The evaluable to hash.
    /// @return evaluableHash Standard hash of the evaluable.
    function hash(EvaluableV2 memory evaluable) internal pure returns (bytes32 evaluableHash) {
        // `Evaluable` does NOT contain any dynamic types so it is safe to encode
        // packed for hashing, and is preferable due to the smaller/simpler
        // in-memory structure. It also makes it easier to replicate the logic
        // offchain as a simple concatenation of bytes.
        assembly ("memory-safe") {
            evaluableHash := keccak256(evaluable, 0x60)
        }
    }

    /// Hashes an `EvaluableV3`, ostensibly so that only the hash need be stored,
    /// thus only storing a single `bytes32` instead of 2x `address` and an
    /// arbitrary length `bytes`.
    /// https://github.com/rainlanguage/rain.lib.hash?tab=readme-ov-file#the-pattern
    /// @param evaluable The evaluable to hash.
    /// @return evaluableHash Standard hash of the evaluable.
    function hash(EvaluableV3 memory evaluable) internal pure returns (bytes32) {
        bytes memory bytecode = evaluable.bytecode;
        bytes32 evaluableHash;
        assembly ("memory-safe") {
            // Hash first fields of evaluable.
            mstore(0, keccak256(evaluable, 0x40))
            // Hash bytecode.
            mstore(0x20, keccak256(add(bytecode, 0x20), mload(bytecode)))

            // Hash the two hashes.
            evaluableHash := keccak256(0, 0x40)
        }
        return evaluableHash;
    }
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.25;

import {Pointer} from "./LibPointer.sol";
import {LibMemCpy} from "./LibMemCpy.sol";
import {OutOfBoundsTruncate} from "../error/ErrUint256Array.sol";

/// @title Uint256Array
/// @notice Things we want to do carefully and efficiently with uint256 arrays
/// that Solidity doesn't give us native tools for.
library LibUint256Array {
    using LibUint256Array for uint256[];

    /// Pointer to the start (length prefix) of a `uint256[]`.
    /// @param array The array to get the start pointer of.
    /// @return pointer The pointer to the start of `array`.
    function startPointer(uint256[] memory array) internal pure returns (Pointer pointer) {
        assembly ("memory-safe") {
            pointer := array
        }
    }

    /// Pointer to the data of a `uint256[]` NOT the length prefix.
    /// @param array The array to get the data pointer of.
    /// @return pointer The pointer to the data of `array`.
    function dataPointer(uint256[] memory array) internal pure returns (Pointer pointer) {
        assembly ("memory-safe") {
            pointer := add(array, 0x20)
        }
    }

    /// Pointer to the end of the allocated memory of an array.
    /// @param array The array to get the end pointer of.
    /// @return pointer The pointer to the end of `array`.
    function endPointer(uint256[] memory array) internal pure returns (Pointer pointer) {
        assembly ("memory-safe") {
            pointer := add(array, add(0x20, mul(0x20, mload(array))))
        }
    }

    /// Cast a `Pointer` to `uint256[]` without modification or safety checks.
    /// The caller MUST ensure the pointer is to a valid region of memory for
    /// some `uint256[]`.
    /// @param pointer The pointer to cast to `uint256[]`.
    /// @return array The cast `uint256[]`.
    function unsafeAsUint256Array(Pointer pointer) internal pure returns (uint256[] memory array) {
        assembly ("memory-safe") {
            array := pointer
        }
    }

    /// Building arrays from literal components is a common task that introduces
    /// boilerplate that is either inefficient or error prone.
    /// @param a A single integer to build an array around.
    /// @return array The newly allocated array including `a` as a single item.
    function arrayFrom(uint256 a) internal pure returns (uint256[] memory array) {
        assembly ("memory-safe") {
            array := mload(0x40)
            mstore(array, 1)
            mstore(add(array, 0x20), a)
            mstore(0x40, add(array, 0x40))
        }
    }

    /// Building arrays from literal components is a common task that introduces
    /// boilerplate that is either inefficient or error prone.
    /// @param a The first integer to build an array around.
    /// @param b The second integer to build an array around.
    /// @return array The newly allocated array including `a` and `b` as the only
    /// items.
    function arrayFrom(uint256 a, uint256 b) internal pure returns (uint256[] memory array) {
        assembly ("memory-safe") {
            array := mload(0x40)
            mstore(array, 2)
            mstore(add(array, 0x20), a)
            mstore(add(array, 0x40), b)
            mstore(0x40, add(array, 0x60))
        }
    }

    /// Building arrays from literal components is a common task that introduces
    /// boilerplate that is either inefficient or error prone.
    /// @param a The first integer to build an array around.
    /// @param b The second integer to build an array around.
    /// @param c The third integer to build an array around.
    /// @return array The newly allocated array including `a`, `b` and `c` as the
    /// only items.
    function arrayFrom(uint256 a, uint256 b, uint256 c) internal pure returns (uint256[] memory array) {
        assembly ("memory-safe") {
            array := mload(0x40)
            mstore(array, 3)
            mstore(add(array, 0x20), a)
            mstore(add(array, 0x40), b)
            mstore(add(array, 0x60), c)
            mstore(0x40, add(array, 0x80))
        }
    }

    /// Building arrays from literal components is a common task that introduces
    /// boilerplate that is either inefficient or error prone.
    /// @param a The first integer to build an array around.
    /// @param b The second integer to build an array around.
    /// @param c The third integer to build an array around.
    /// @param d The fourth integer to build an array around.
    /// @return array The newly allocated array including `a`, `b`, `c` and `d` as the
    /// only items.
    function arrayFrom(uint256 a, uint256 b, uint256 c, uint256 d) internal pure returns (uint256[] memory array) {
        assembly ("memory-safe") {
            array := mload(0x40)
            mstore(array, 4)
            mstore(add(array, 0x20), a)
            mstore(add(array, 0x40), b)
            mstore(add(array, 0x60), c)
            mstore(add(array, 0x80), d)
            mstore(0x40, add(array, 0xA0))
        }
    }

    /// Building arrays from literal components is a common task that introduces
    /// boilerplate that is either inefficient or error prone.
    /// @param a The first integer to build an array around.
    /// @param b The second integer to build an array around.
    /// @param c The third integer to build an array around.
    /// @param d The fourth integer to build an array around.
    /// @param e The fifth integer to build an array around.
    /// @return array The newly allocated array including `a`, `b`, `c`, `d` and
    /// `e` as the only items.
    function arrayFrom(uint256 a, uint256 b, uint256 c, uint256 d, uint256 e)
        internal
        pure
        returns (uint256[] memory array)
    {
        assembly ("memory-safe") {
            array := mload(0x40)
            mstore(array, 5)
            mstore(add(array, 0x20), a)
            mstore(add(array, 0x40), b)
            mstore(add(array, 0x60), c)
            mstore(add(array, 0x80), d)
            mstore(add(array, 0xA0), e)
            mstore(0x40, add(array, 0xC0))
        }
    }

    /// Building arrays from literal components is a common task that introduces
    /// boilerplate that is either inefficient or error prone.
    /// @param a The first integer to build an array around.
    /// @param b The second integer to build an array around.
    /// @param c The third integer to build an array around.
    /// @param d The fourth integer to build an array around.
    /// @param e The fifth integer to build an array around.
    /// @param f The sixth integer to build an array around.
    /// @return array The newly allocated array including `a`, `b`, `c`, `d`, `e`
    /// and `f` as the only items.
    function arrayFrom(uint256 a, uint256 b, uint256 c, uint256 d, uint256 e, uint256 f)
        internal
        pure
        returns (uint256[] memory array)
    {
        assembly ("memory-safe") {
            array := mload(0x40)
            mstore(array, 6)
            mstore(add(array, 0x20), a)
            mstore(add(array, 0x40), b)
            mstore(add(array, 0x60), c)
            mstore(add(array, 0x80), d)
            mstore(add(array, 0xA0), e)
            mstore(add(array, 0xC0), f)
            mstore(0x40, add(array, 0xE0))
        }
    }

    /// Building arrays from literal components is a common task that introduces
    /// boilerplate that is either inefficient or error prone.
    /// @param a The first integer to build an array around.
    /// @param b The second integer to build an array around.
    /// @param c The third integer to build an array around.
    /// @param d The fourth integer to build an array around.
    /// @param e The fifth integer to build an array around.
    /// @param f The sixth integer to build an array around.
    /// @param g The seventh integer to build an array around.
    /// @return array The newly allocated array including `a`, `b`, `c`, `d`, `e`,
    /// `f` and `g` as the only items.
    function arrayFrom(uint256 a, uint256 b, uint256 c, uint256 d, uint256 e, uint256 f, uint256 g)
        internal
        pure
        returns (uint256[] memory array)
    {
        assembly ("memory-safe") {
            array := mload(0x40)
            mstore(array, 7)
            mstore(add(array, 0x20), a)
            mstore(add(array, 0x40), b)
            mstore(add(array, 0x60), c)
            mstore(add(array, 0x80), d)
            mstore(add(array, 0xA0), e)
            mstore(add(array, 0xC0), f)
            mstore(add(array, 0xE0), g)
            mstore(0x40, add(array, 0x100))
        }
    }

    /// Building arrays from literal components is a common task that introduces
    /// boilerplate that is either inefficient or error prone.
    /// @param a The first integer to build an array around.
    /// @param b The second integer to build an array around.
    /// @param c The third integer to build an array around.
    /// @param d The fourth integer to build an array around.
    /// @param e The fifth integer to build an array around.
    /// @param f The sixth integer to build an array around.
    /// @param g The seventh integer to build an array around.
    /// @param h The eighth integer to build an array around.
    /// @return array The newly allocated array including `a`, `b`, `c`, `d`, `e`,
    /// `f`, `g` and `h` as the only items.
    function arrayFrom(uint256 a, uint256 b, uint256 c, uint256 d, uint256 e, uint256 f, uint256 g, uint256 h)
        internal
        pure
        returns (uint256[] memory array)
    {
        assembly ("memory-safe") {
            array := mload(0x40)
            mstore(array, 8)
            mstore(add(array, 0x20), a)
            mstore(add(array, 0x40), b)
            mstore(add(array, 0x60), c)
            mstore(add(array, 0x80), d)
            mstore(add(array, 0xA0), e)
            mstore(add(array, 0xC0), f)
            mstore(add(array, 0xE0), g)
            mstore(add(array, 0x100), h)
            mstore(0x40, add(array, 0x120))
        }
    }

    /// Building arrays from literal components is a common task that introduces
    /// boilerplate that is either inefficient or error prone.
    /// @param a The head of the new array.
    /// @param tail The tail of the new array.
    /// @return array The new array.
    function arrayFrom(uint256 a, uint256[] memory tail) internal pure returns (uint256[] memory array) {
        assembly ("memory-safe") {
            let length := add(mload(tail), 1)
            let outputCursor := mload(0x40)
            array := outputCursor
            let outputEnd := add(outputCursor, add(0x20, mul(length, 0x20)))
            mstore(0x40, outputEnd)

            mstore(outputCursor, length)
            mstore(add(outputCursor, 0x20), a)

            for {
                outputCursor := add(outputCursor, 0x40)
                let inputCursor := add(tail, 0x20)
            } lt(outputCursor, outputEnd) {
                outputCursor := add(outputCursor, 0x20)
                inputCursor := add(inputCursor, 0x20)
            } { mstore(outputCursor, mload(inputCursor)) }
        }
    }

    /// Building arrays from literal components is a common task that introduces
    /// boilerplate that is either inefficient or error prone.
    /// @param a The first item of the new array.
    /// @param b The second item of the new array.
    /// @param tail The tail of the new array.
    /// @return array The new array.
    function arrayFrom(uint256 a, uint256 b, uint256[] memory tail) internal pure returns (uint256[] memory array) {
        assembly ("memory-safe") {
            let length := add(mload(tail), 2)
            let outputCursor := mload(0x40)
            array := outputCursor
            let outputEnd := add(outputCursor, add(0x20, mul(length, 0x20)))
            mstore(0x40, outputEnd)

            mstore(outputCursor, length)
            mstore(add(outputCursor, 0x20), a)
            mstore(add(outputCursor, 0x40), b)

            for {
                outputCursor := add(outputCursor, 0x60)
                let inputCursor := add(tail, 0x20)
            } lt(outputCursor, outputEnd) {
                outputCursor := add(outputCursor, 0x20)
                inputCursor := add(inputCursor, 0x20)
            } { mstore(outputCursor, mload(inputCursor)) }
        }
    }

    /// Solidity provides no way to change the length of in-memory arrays but
    /// it also does not deallocate memory ever. It is always safe to shrink an
    /// array that has already been allocated, with the caveat that the
    /// truncated items will effectively become inaccessible regions of memory.
    /// That is to say, we deliberately "leak" the truncated items, but that is
    /// no worse than Solidity's native behaviour of leaking everything always.
    /// The array is MUTATED in place so there is no return value and there is
    /// no new allocation or copying of data either.
    /// @param array The array to truncate.
    /// @param newLength The new length of the array after truncation.
    function truncate(uint256[] memory array, uint256 newLength) internal pure {
        if (newLength > array.length) {
            revert OutOfBoundsTruncate(array.length, newLength);
        }
        assembly ("memory-safe") {
            mstore(array, newLength)
        }
    }

    /// Extends `base_` with `extend_` by allocating only an additional
    /// `extend_.length` words onto `base_` and copying only `extend_` if
    /// possible. If `base_` is large this MAY be significantly more efficient
    /// than allocating `base_.length + extend_.length` for an entirely new array
    /// and copying both `base_` and `extend_` into the new array one item at a
    /// time in Solidity.
    ///
    /// The efficient version of extension is only possible if the free memory
    /// pointer sits at the end of the base array at the moment of extension. If
    /// there is allocated memory after the end of base then extension will
    /// require copying both the base and extend arays to a new region of memory.
    /// The caller is responsible for optimising code paths to avoid additional
    /// allocations.
    ///
    /// This function is UNSAFE because the base array IS MUTATED DIRECTLY by
    /// some code paths AND THE FINAL RETURN ARRAY MAY POINT TO THE SAME REGION
    /// OF MEMORY. It is NOT POSSIBLE to reliably see this behaviour from the
    /// caller in all cases as the Solidity compiler optimisations may switch the
    /// caller between the allocating and non-allocating logic due to subtle
    /// optimisation reasons. To use this function safely THE CALLER MUST NOT USE
    /// THE BASE ARRAY AND MUST USE THE RETURNED ARRAY ONLY. It is safe to use
    /// the extend array after calling this function as it is never mutated, it
    /// is only copied from.
    ///
    /// @param b The base integer array that will be extended by `e`.
    /// @param e The extend integer array that extends `b`.
    /// @return extended The extended array of `b` extended by `e`.
    function unsafeExtend(uint256[] memory b, uint256[] memory e) internal pure returns (uint256[] memory extended) {
        assembly ("memory-safe") {
            // Slither doesn't recognise assembly function names as mixed case
            // even if they are.
            // https://github.com/crytic/slither/issues/1815
            //slither-disable-next-line naming-convention
            function extendInline(base, extend) -> baseAfter {
                let outputCursor := mload(0x40)
                let baseLength := mload(base)
                let baseEnd := add(base, add(0x20, mul(baseLength, 0x20)))

                // If base is NOT the last thing in allocated memory, allocate,
                // copy and recurse.
                switch eq(outputCursor, baseEnd)
                case 0 {
                    let newBase := outputCursor
                    let newBaseEnd := add(newBase, sub(baseEnd, base))
                    mstore(0x40, newBaseEnd)
                    for { let inputCursor := base } lt(outputCursor, newBaseEnd) {
                        inputCursor := add(inputCursor, 0x20)
                        outputCursor := add(outputCursor, 0x20)
                    } { mstore(outputCursor, mload(inputCursor)) }

                    baseAfter := extendInline(newBase, extend)
                }
                case 1 {
                    let totalLength_ := add(baseLength, mload(extend))
                    let outputEnd_ := add(base, add(0x20, mul(totalLength_, 0x20)))
                    mstore(base, totalLength_)
                    mstore(0x40, outputEnd_)
                    for { let inputCursor := add(extend, 0x20) } lt(outputCursor, outputEnd_) {
                        inputCursor := add(inputCursor, 0x20)
                        outputCursor := add(outputCursor, 0x20)
                    } { mstore(outputCursor, mload(inputCursor)) }

                    baseAfter := base
                }
            }

            extended := extendInline(b, e)
        }
    }

    /// Reverse an array in place. This is a destructive operation that MUTATES
    /// the array in place. There is no return value.
    /// @param array The array to reverse.
    function reverse(uint256[] memory array) internal pure {
        assembly ("memory-safe") {
            for {
                let left := add(array, 0x20)
                // Right points at the last item in the array. Which is the
                // length number of items from the length.
                let right := add(array, mul(mload(array), 0x20))
            } lt(left, right) {
                left := add(left, 0x20)
                right := sub(right, 0x20)
            } {
                let leftValue := mload(left)
                mstore(left, mload(right))
                mstore(right, leftValue)
            }
        }
    }
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

bytes32 constant HASH_NIL = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;

/// @title LibHashNoAlloc
/// @notice When producing hashes of just about anything that isn't already bytes
/// the common suggestions look something like `keccak256(abi.encode(...))` or
/// `keccak256(abi.encodePacked(...))` with the main differentiation being
/// whether dynamic data types are being hashed. If they are then there is a hash
/// collision risk in the packed case as `"abc" + "def"` and `"ab" + "cdef"` will
/// pack and therefore hash to the same values, the suggested fix commonly being
/// to use abi.encode, which includes the lengths disambiguating dynamic data.
/// Something like `3"abc" + 3"def"` with the length prefixes won't collide with
/// `2"ab" + 4"cdef"` but note that ABI provides neither a strong guarantee to
/// be collision resitant on inputs (as far as I know, it's a coincidence that
/// this works), nor an efficient solution.
///
/// - Abi encoding is a complex algorithm that is easily 1k+ gas for simple
///   structs with just one or two dynamic typed fields.
/// - Abi encoding requires allocating and copying all the data plus a header to
///   a new region of memory, which gives it non-linearly increasing costs due to
///   memory expansion.
/// - Abi encoding can't easily be reproduced offchain without specialised tools,
///   it's not simply a matter of length prefixing some byte string and hashing
///   with keccak256, the heads and tails all need to be produced recursively
///   https://docs.soliditylang.org/en/develop/abi-spec.html#formal-specification-of-the-encoding
///
/// Consider that `hash(hash("abc") + hash("def"))` won't collide with
/// `hash(hash("ab") + hash("cdef"))`. It should be easier to convince ourselves
/// this is true for all possible pairs of byte strings than it is to convince
/// ourselves that the ABI serialization is never ambigious. Inductively we can
/// scale this to all possible data structures that are ordered compositions of
/// byte strings. Even better, the native behaviour of `keccak256` in the EVM
/// requires no additional allocation of memory. Worst case scenario is that we
/// want to hash several hashes together like `hash(hash0, hash1, ...)`, in which
/// case we can write the words after the free memory pointer, hash them, but
/// leave the pointer. This way we pay for memory expansion but can re-use that
/// region of memory for subsequent logic, which may effectively make the
/// expansion free as we would have needed to pay for it anyway. Given that hash
/// checks often occur early in real world logic due to
/// checks-effects-interactions, this is not an unreasonable assumption to call
/// this kind of expansion "no alloc".
///
/// One problem is that the gas saving for trivial abi encoding,
/// e.g. ~1-3 uint256 values, can be lost by the overhead of jumps and stack
/// manipulation due to function calls.
///
/// ```
/// struct Foo {
///   uint256 a;
///   address b;
///   uint32 c;
/// }
/// ```
/// The simplest way to hash `Foo` is to just hash it (crazy, i know!).
///
/// ```
/// assembly ("memory-safe") {
///   hash_ := keccak256(foo_, 0x60)
/// }
/// ```
/// Every struct field is 0x20 bytes in memory so 3 fields = 0x60 bytes to hash
/// always, with the exception of dynamic types. This costs about 70 gas vs.
/// about 350 gas for an abi encoding based approach.
library LibHashNoAlloc {
    function hashBytes(bytes memory data_) internal pure returns (bytes32 hash_) {
        assembly ("memory-safe") {
            hash_ := keccak256(add(data_, 0x20), mload(data_))
        }
    }

    function hashWords(bytes32[] memory words_) internal pure returns (bytes32 hash_) {
        assembly ("memory-safe") {
            hash_ := keccak256(add(words_, 0x20), mul(mload(words_), 0x20))
        }
    }

    function hashWords(uint256[] memory words_) internal pure returns (bytes32 hash_) {
        assembly ("memory-safe") {
            hash_ := keccak256(add(words_, 0x20), mul(mload(words_), 0x20))
        }
    }

    function combineHashes(bytes32 a_, bytes32 b_) internal pure returns (bytes32 hash_) {
        assembly ("memory-safe") {
            mstore(0, a_)
            mstore(0x20, b_)
            hash_ := keccak256(0, 0x40)
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/SignatureChecker.sol)

pragma solidity ^0.8.0;

import "./ECDSA.sol";
import "../../interfaces/IERC1271.sol";

/**
 * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA
 * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like
 * Argent and Gnosis Safe.
 *
 * _Available since v4.1._
 */
library SignatureChecker {
    /**
     * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the
     * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.
     *
     * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
     * change through time. It could return true at block N and false at block N+1 (or the opposite).
     */
    function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {
        (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);
        return
            (error == ECDSA.RecoverError.NoError && recovered == signer) ||
            isValidERC1271SignatureNow(signer, hash, signature);
    }

    /**
     * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated
     * against the signer smart contract using ERC1271.
     *
     * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
     * change through time. It could return true at block N and false at block N+1 (or the opposite).
     */
    function isValidERC1271SignatureNow(
        address signer,
        bytes32 hash,
        bytes memory signature
    ) internal view returns (bool) {
        (bool success, bytes memory result) = signer.staticcall(
            abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)
        );
        return (success &&
            result.length >= 32 &&
            abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "../Strings.sol";

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV // Deprecated in v4.8
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, "\x19Ethereum Signed Message:\n32")
            mstore(0x1c, hash)
            message := keccak256(0x00, 0x3c)
        }
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, "\x19\x01")
            mstore(add(ptr, 0x02), domainSeparator)
            mstore(add(ptr, 0x22), structHash)
            data := keccak256(ptr, 0x42)
        }
    }

    /**
     * @dev Returns an Ethereum Signed Data with intended validator, created from a
     * `validator` and `data` according to the version 0 of EIP-191.
     *
     * See {recover}.
     */
    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x00", validator, data));
    }
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.25;

/// A pointer to a location in memory. This is a `uint256` to save gas on low
/// level operations on the evm stack. These same low level operations typically
/// WILL NOT check for overflow or underflow, so all pointer logic MUST ensure
/// that reads, writes and movements are not out of bounds.
type Pointer is uint256;

/// @title LibPointer
/// Ergonomic wrappers around common pointer movements, reading and writing. As
/// wrappers on such low level operations often introduce too much jump gas
/// overhead, these functions MAY find themselves used in reference
/// implementations that more optimised code can be fuzzed against. MAY also be
/// situationally useful on cooler performance paths.
library LibPointer {
    /// Cast a `Pointer` to `bytes` without modification or any safety checks.
    /// The caller MUST ensure the pointer is to a valid region of memory for
    /// some `bytes`.
    /// @param pointer The pointer to cast to `bytes`.
    /// @return data The cast `bytes`.
    function unsafeAsBytes(Pointer pointer) internal pure returns (bytes memory data) {
        assembly ("memory-safe") {
            data := pointer
        }
    }

    /// Increase some pointer by a number of bytes.
    ///
    /// This is UNSAFE because it can silently overflow or point beyond some
    /// data structure. The caller MUST ensure that this is a safe operation.
    ///
    /// Note that moving a pointer by some bytes offset is likely to unalign it
    /// with the 32 byte increments of the Solidity allocator.
    ///
    /// @param pointer The pointer to increase by `length`.
    /// @param length The number of bytes to increase the pointer by.
    /// @return The increased pointer.
    function unsafeAddBytes(Pointer pointer, uint256 length) internal pure returns (Pointer) {
        assembly ("memory-safe") {
            pointer := add(pointer, length)
        }
        return pointer;
    }

    /// Increase some pointer by a single 32 byte word.
    ///
    /// This is UNSAFE because it can silently overflow or point beyond some
    /// data structure. The caller MUST ensure that this is a safe operation.
    ///
    /// If the original pointer is aligned to the Solidity allocator it will be
    /// aligned after the movement.
    ///
    /// @param pointer The pointer to increase by a single word.
    /// @return The increased pointer.
    function unsafeAddWord(Pointer pointer) internal pure returns (Pointer) {
        assembly ("memory-safe") {
            pointer := add(pointer, 0x20)
        }
        return pointer;
    }

    /// Increase some pointer by multiple 32 byte words.
    ///
    /// This is UNSAFE because it can silently overflow or point beyond some
    /// data structure. The caller MUST ensure that this is a safe operation.
    ///
    /// If the original pointer is aligned to the Solidity allocator it will be
    /// aligned after the movement.
    ///
    /// @param pointer The pointer to increase.
    /// @param words The number of words to increase the pointer by.
    /// @return The increased pointer.
    function unsafeAddWords(Pointer pointer, uint256 words) internal pure returns (Pointer) {
        assembly ("memory-safe") {
            pointer := add(pointer, mul(0x20, words))
        }
        return pointer;
    }

    /// Decrease some pointer by a single 32 byte word.
    ///
    /// This is UNSAFE because it can silently underflow or point below some
    /// data structure. The caller MUST ensure that this is a safe operation.
    ///
    /// If the original pointer is aligned to the Solidity allocator it will be
    /// aligned after the movement.
    ///
    /// @param pointer The pointer to decrease by a single word.
    /// @return The decreased pointer.
    function unsafeSubWord(Pointer pointer) internal pure returns (Pointer) {
        assembly ("memory-safe") {
            pointer := sub(pointer, 0x20)
        }
        return pointer;
    }

    /// Decrease some pointer by multiple 32 byte words.
    ///
    /// This is UNSAFE because it can silently underflow or point below some
    /// data structure. The caller MUST ensure that this is a safe operation.
    ///
    /// If the original pointer is aligned to the Solidity allocator it will be
    /// aligned after the movement.
    ///
    /// @param pointer The pointer to decrease.
    /// @param words The number of words to decrease the pointer by.
    /// @return The decreased pointer.
    function unsafeSubWords(Pointer pointer, uint256 words) internal pure returns (Pointer) {
        assembly ("memory-safe") {
            pointer := sub(pointer, mul(0x20, words))
        }
        return pointer;
    }

    /// Read the word at the pointer.
    ///
    /// This is UNSAFE because it can read outside any particular data stucture
    /// or even beyond allocated memory. The caller MUST ensure that this is a
    /// safe operation.
    ///
    /// @param pointer Pointer to read the word at.
    /// @return word The word read from the pointer.
    function unsafeReadWord(Pointer pointer) internal pure returns (uint256 word) {
        assembly ("memory-safe") {
            word := mload(pointer)
        }
    }

    /// Write a word at the pointer.
    ///
    /// This is UNSAFE because it can write outside any particular data stucture
    /// or even beyond allocated memory. The caller MUST ensure that this is a
    /// safe operation.
    ///
    /// @param pointer Pointer to write the word at.
    /// @param word The word to write.
    function unsafeWriteWord(Pointer pointer, uint256 word) internal pure {
        assembly ("memory-safe") {
            mstore(pointer, word)
        }
    }

    /// Get the pointer to the end of all allocated memory.
    /// As per Solidity docs, there is no guarantee that the region of memory
    /// beyond this pointer is zeroed out, as assembly MAY write beyond allocated
    /// memory for temporary use if the scratch space is insufficient.
    /// @return pointer The pointer to the end of all allocated memory.
    function allocatedMemoryPointer() internal pure returns (Pointer pointer) {
        assembly ("memory-safe") {
            pointer := mload(0x40)
        }
    }
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.25;

import "./LibPointer.sol";

/// Thrown when asked to truncate data to a longer length.
/// @param length Actual bytes length.
/// @param truncate Attempted truncation length.
error TruncateError(uint256 length, uint256 truncate);

/// @title LibBytes
/// @notice Tools for working directly with memory in a Solidity compatible way.
library LibBytes {
    /// Truncates bytes of data by mutating its length directly.
    /// Any excess bytes are leaked
    function truncate(bytes memory data, uint256 length) internal pure {
        if (data.length < length) {
            revert TruncateError(data.length, length);
        }
        assembly ("memory-safe") {
            mstore(data, length)
        }
    }

    /// Pointer to the data of a bytes array NOT the length prefix.
    /// @param data Bytes to get the data pointer for.
    /// @return pointer Pointer to the data of the bytes in memory.
    function dataPointer(bytes memory data) internal pure returns (Pointer pointer) {
        assembly ("memory-safe") {
            pointer := add(data, 0x20)
        }
    }

    /// Pointer to the start of a bytes array (the length prefix).
    /// @param data Bytes to get the pointer to.
    /// @return pointer Pointer to the start of the bytes data structure.
    function startPointer(bytes memory data) internal pure returns (Pointer pointer) {
        assembly ("memory-safe") {
            pointer := data
        }
    }

    /// Pointer to the end of some bytes.
    ///
    /// Note that this pointer MAY NOT BE ALIGNED, i.e. it MAY NOT point to the
    /// start of a multiple of 32, UNLIKE the free memory pointer at 0x40.
    ///
    /// @param data Bytes to get the pointer to the end of.
    /// @return pointer Pointer to the end of the bytes data structure.
    function endDataPointer(bytes memory data) internal pure returns (Pointer pointer) {
        assembly ("memory-safe") {
            pointer := add(data, add(0x20, mload(data)))
        }
    }

    /// Pointer to the end of the memory allocated for bytes.
    ///
    /// The allocator is ALWAYS aligned to whole words, i.e. 32 byte multiples,
    /// for data structures allocated by Solidity. This includes `bytes` which
    /// means that any time the length of some `bytes` is NOT a multiple of 32
    /// the alloation will point past the end of the `bytes` data.
    ///
    /// There is no guarantee that the memory region between `endDataPointer`
    /// and `endAllocatedPointer` is zeroed out. It is best to think of that
    /// space as leaked garbage.
    ///
    /// Almost always, e.g. for the purpose of copying data between regions, you
    /// will want `endDataPointer` rather than this function.
    /// @param data Bytes to get the end of the allocated data region for.
    /// @return pointer Pointer to the end of the allocated data region.
    function endAllocatedPointer(bytes memory data) internal pure returns (Pointer pointer) {
        assembly ("memory-safe") {
            pointer := add(data, and(add(add(mload(data), 0x20), 0x1f), not(0x1f)))
        }
    }
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.25;

import "./LibPointer.sol";

library LibMemCpy {
    /// Copy an arbitrary number of bytes from one location in memory to another.
    /// As we can only read/write bytes in 32 byte chunks we first have to loop
    /// over 32 byte values to copy then handle any unaligned remaining data. The
    /// remaining data will be appropriately masked with the existing data in the
    /// final chunk so as to not write past the desired length. Note that the
    /// final unaligned write will be more gas intensive than the prior aligned
    /// writes. The writes are completely unsafe, the caller MUST ensure that
    /// sufficient memory is allocated and reading/writing the requested number
    /// of bytes from/to the requested locations WILL NOT corrupt memory in the
    /// opinion of solidity or other subsequent read/write operations.
    /// @param sourceCursor The starting pointer to read from.
    /// @param targetCursor The starting pointer to write to.
    /// @param length The number of bytes to read/write.
    function unsafeCopyBytesTo(Pointer sourceCursor, Pointer targetCursor, uint256 length) internal pure {
        assembly ("memory-safe") {
            // Precalculating the end here, rather than tracking the remaining
            // length each iteration uses relatively more gas for less data, but
            // scales better for more data. Copying 1-2 words is ~30 gas more
            // expensive but copying 3+ words favours a precalculated end point
            // increasingly for more data.
            let m := mod(length, 0x20)
            let end := add(sourceCursor, sub(length, m))
            for {} lt(sourceCursor, end) {
                sourceCursor := add(sourceCursor, 0x20)
                targetCursor := add(targetCursor, 0x20)
            } { mstore(targetCursor, mload(sourceCursor)) }

            if iszero(iszero(m)) {
                //slither-disable-next-line incorrect-shift
                let mask := shr(mul(m, 8), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
                // preserve existing bytes
                mstore(
                    targetCursor,
                    or(
                        // input
                        and(mload(sourceCursor), not(mask)),
                        and(mload(targetCursor), mask)
                    )
                )
            }
        }
    }

    /// Copies `length` `uint256` values starting from `source` to `target`
    /// with NO attempt to check that this is safe to do so. The caller MUST
    /// ensure that there exists allocated memory at `target` in which it is
    /// safe and appropriate to copy `length * 32` bytes to. Anything that was
    /// already written to memory at `[target:target+(length * 32 bytes)]`
    /// will be overwritten.
    /// There is no return value as memory is modified directly.
    /// @param source The starting position in memory that data will be copied
    /// from.
    /// @param target The starting position in memory that data will be copied
    /// to.
    /// @param length The number of 32 byte (i.e. `uint256`) words that will
    /// be copied.
    function unsafeCopyWordsTo(Pointer source, Pointer target, uint256 length) internal pure {
        assembly ("memory-safe") {
            for { let end := add(source, mul(0x20, length)) } lt(source, end) {
                source := add(source, 0x20)
                target := add(target, 0x20)
            } { mstore(target, mload(source)) }
        }
    }
}

File 36 of 55 : ErrBytecode.sol
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.25;

/// @dev Workaround for https://github.com/foundry-rs/foundry/issues/6572
contract ErrBytecode {}

/// Thrown when a bytecode source index is out of bounds.
/// @param sourceIndex The source index that was out of bounds.
/// @param bytecode The bytecode that was inspected.
error SourceIndexOutOfBounds(uint256 sourceIndex, bytes bytecode);

/// Thrown when a bytecode reports itself as 0 sources but has more than 1 byte.
/// @param bytecode The bytecode that was inspected.
error UnexpectedSources(bytes bytecode);

/// Thrown when bytes are discovered between the offsets and the sources.
/// @param bytecode The bytecode that was inspected.
error UnexpectedTrailingOffsetBytes(bytes bytecode);

/// Thrown when the end of a source as self reported by its header doesnt match
/// the start of the next source or the end of the bytecode.
/// @param bytecode The bytecode that was inspected.
error TruncatedSource(bytes bytecode);

/// Thrown when the offset to a source points to a location that cannot fit a
/// header before the start of the next source or the end of the bytecode.
/// @param bytecode The bytecode that was inspected.
error TruncatedHeader(bytes bytecode);

/// Thrown when the bytecode is truncated before the end of the header offsets.
/// @param bytecode The bytecode that was inspected.
error TruncatedHeaderOffsets(bytes bytecode);

/// Thrown when the stack sizings, allocation, inputs and outputs, are not
/// monotonically increasing.
/// @param bytecode The bytecode that was inspected.
/// @param relativeOffset The relative offset of the source that was inspected.
error StackSizingsNotMonotonic(bytes bytecode, uint256 relativeOffset);

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.25;

import {
    FIXED_POINT_ONE,
    FLAG_SATURATE,
    FLAG_ROUND_UP,
    FIXED_POINT_DECIMALS,
    OVERFLOW_RESCALE_OOMS,
    DECIMAL_MAX_SAFE_INT
} from "./FixedPointDecimalConstants.sol";
import {ErrScaleDownPrecisionLoss, IntegerOverflow} from "../error/ErrScale.sol";

/// @title FixedPointDecimalScale
/// @notice Tools to scale unsigned values to/from 18 decimal fixed point
/// representation.
///
/// Overflows error and underflows are rounded up or down explicitly.
///
/// The max uint256 as decimal is roughly 1e77 so scaling values comparable to
/// 1e18 is unlikely to ever overflow in most contexts. For a typical use case
/// involving tokens, the entire supply of a token rescaled up a full 18 decimals
/// would still put it "only" in the region of ~1e40 which has a full 30 orders
/// of magnitude buffer before running into saturation issues. However, there's
/// no theoretical reason that a token or any other use case couldn't use large
/// numbers or extremely precise decimals that would push this library to
/// overflow point, so it MUST be treated with caution around the edge cases.
///
/// Scaling down ANY fixed point decimal also reduces the precision which can
/// lead to  dust or in the worst case trapped funds if subsequent subtraction
/// overflows a rounded-down number. Consider using saturating subtraction for
/// safety against previously downscaled values, and whether trapped dust is a
/// significant issue. If you need to retain full/arbitrary precision in the case
/// of downscaling DO NOT use this library.
///
/// All rescaling and/or division operations in this library require a rounding
/// flag. This allows and forces the caller to specify where dust sits due to
/// rounding. For example the caller could round up when taking tokens from
/// `msg.sender` and round down when returning them, ensuring that any dust in
/// the round trip accumulates in the contract rather than opening an exploit or
/// reverting and trapping all funds. This is exactly how the ERC4626 vault spec
/// handles dust and is a good reference point in general. Typically the contract
/// holding tokens and non-interactive participants should be favoured by
/// rounding calculations rather than active participants. This is because we
/// assume that an active participant, e.g. `msg.sender`, knowns something we
/// don't and is carefully crafting an attack, so we are most conservative and
/// suspicious of their inputs and actions.
library LibFixedPointDecimalScale {
    /// Scales `a` up by a specified number of decimals.
    /// @param a The number to scale up.
    /// @param scaleUpBy Number of orders of magnitude to scale `b_` up by.
    /// Errors if overflows.
    /// @return b `a` scaled up by `scaleUpBy`.
    function scaleUp(uint256 a, uint256 scaleUpBy) internal pure returns (uint256 b) {
        // Checked power is expensive so don't do that.
        unchecked {
            b = 10 ** scaleUpBy;
        }
        b = a * b;

        // We know exactly when 10 ** X overflows so replay the checked version
        // to get the standard Solidity overflow behaviour. The branching logic
        // here is still ~230 gas cheaper than unconditionally running the
        // overflow checks. We're optimising for standardisation rather than gas
        // in the unhappy revert case.
        if (scaleUpBy >= OVERFLOW_RESCALE_OOMS) {
            b = a == 0 ? 0 : 10 ** scaleUpBy;
        }
    }

    /// Identical to `scaleUp` but saturates instead of reverting on overflow.
    /// @param a As per `scaleUp`.
    /// @param scaleUpBy As per `scaleUp`.
    /// @return c As per `scaleUp` but saturates as `type(uint256).max` on
    /// overflow.
    function scaleUpSaturating(uint256 a, uint256 scaleUpBy) internal pure returns (uint256 c) {
        unchecked {
            if (scaleUpBy >= OVERFLOW_RESCALE_OOMS) {
                c = a == 0 ? 0 : type(uint256).max;
            } else {
                // Adapted from saturatingMath.
                // Inlining everything here saves ~250-300+ gas relative to slow.
                uint256 b_ = 10 ** scaleUpBy;
                c = a * b_;
                // Checking b_ here allows us to skip an "is zero" check because even
                // 10 ** 0 = 1, so we have a positive lower bound on b_.
                c = c / b_ == a ? c : type(uint256).max;
            }
        }
    }

    /// Scales `a` down by a specified number of decimals, rounding down.
    /// Used internally by several other functions in this lib.
    /// @param a The number to scale down.
    /// @param scaleDownBy Number of orders of magnitude to scale `a` down by.
    /// Overflows if greater than 77.
    /// @return c `a` scaled down by `scaleDownBy` and rounded down.
    function scaleDown(uint256 a, uint256 scaleDownBy) internal pure returns (uint256) {
        unchecked {
            return scaleDownBy >= OVERFLOW_RESCALE_OOMS ? 0 : a / (10 ** scaleDownBy);
        }
    }

    /// Scales `a` down by a specified number of decimals, rounding up.
    /// Used internally by several other functions in this lib.
    /// @param a The number to scale down.
    /// @param scaleDownBy Number of orders of magnitude to scale `a` down by.
    /// Overflows if greater than 77.
    /// @return c `a` scaled down by `scaleDownBy` and rounded up.
    function scaleDownRoundUp(uint256 a, uint256 scaleDownBy) internal pure returns (uint256 c) {
        unchecked {
            if (scaleDownBy >= OVERFLOW_RESCALE_OOMS) {
                c = a == 0 ? 0 : 1;
            } else {
                uint256 b = 10 ** scaleDownBy;
                c = a / b;

                // Intentionally doing a divide before multiply here to detect
                // the need to round up.
                //slither-disable-next-line divide-before-multiply
                if (a != c * b) {
                    c += 1;
                }
            }
        }
    }

    /// Scale a fixed point decimal of some scale factor to 18 decimals.
    /// @param a Some fixed point decimal value.
    /// @param decimals The number of fixed decimals of `a`.
    /// @param flags Controls rounding and saturation.
    /// @return `a` scaled to 18 decimals.
    function scale18(uint256 a, uint256 decimals, uint256 flags) internal pure returns (uint256) {
        unchecked {
            if (FIXED_POINT_DECIMALS > decimals) {
                uint256 scaleUpBy = FIXED_POINT_DECIMALS - decimals;
                if (flags & FLAG_SATURATE > 0) {
                    return scaleUpSaturating(a, scaleUpBy);
                } else {
                    return scaleUp(a, scaleUpBy);
                }
            } else if (decimals > FIXED_POINT_DECIMALS) {
                uint256 scaleDownBy = decimals - FIXED_POINT_DECIMALS;
                if (flags & FLAG_ROUND_UP > 0) {
                    return scaleDownRoundUp(a, scaleDownBy);
                } else {
                    return scaleDown(a, scaleDownBy);
                }
            } else {
                return a;
            }
        }
    }

    /// Scale an 18 decimal fixed point value to some other scale.
    /// Exactly the inverse behaviour of `scale18`. Where `scale18` would scale
    /// up, `scaleN` scales down, and vice versa.
    /// @param a An 18 decimal fixed point number.
    /// @param targetDecimals The new scale of `a`.
    /// @param flags Controls rounding and saturation.
    /// @return `a` rescaled from 18 to `targetDecimals`.
    function scaleN(uint256 a, uint256 targetDecimals, uint256 flags) internal pure returns (uint256) {
        unchecked {
            if (FIXED_POINT_DECIMALS > targetDecimals) {
                uint256 scaleDownBy = FIXED_POINT_DECIMALS - targetDecimals;
                if (flags & FLAG_ROUND_UP > 0) {
                    return scaleDownRoundUp(a, scaleDownBy);
                } else {
                    return scaleDown(a, scaleDownBy);
                }
            } else if (targetDecimals > FIXED_POINT_DECIMALS) {
                uint256 scaleUpBy = targetDecimals - FIXED_POINT_DECIMALS;
                if (flags & FLAG_SATURATE > 0) {
                    return scaleUpSaturating(a, scaleUpBy);
                } else {
                    return scaleUp(a, scaleUpBy);
                }
            } else {
                return a;
            }
        }
    }

    /// Scale a fixed point up or down by `ooms` orders of magnitude.
    /// Notably `scaleBy` is a SIGNED integer so scaling down by negative OOMS
    /// IS supported.
    /// @param a Some integer of any scale.
    /// @param ooms OOMs to scale `a` up or down by. This is a SIGNED int8
    /// which means it can be negative, and also means that sign extension MUST
    /// be considered if changing it to another type.
    /// @param flags Controls rounding and saturating.
    /// @return `a` rescaled according to `ooms`.
    function scaleBy(uint256 a, int8 ooms, uint256 flags) internal pure returns (uint256) {
        unchecked {
            if (ooms > 0) {
                if (flags & FLAG_SATURATE > 0) {
                    return scaleUpSaturating(a, uint8(ooms));
                } else {
                    return scaleUp(a, uint8(ooms));
                }
            } else if (ooms < 0) {
                // We know that ooms is negative here, so we can convert it
                // to an absolute value with bitwise NOT + 1.
                // This is slightly less gas than multiplying by negative 1 and
                // casting it, and handles the case of -128 without overflow.
                uint8 scaleDownBy = uint8(~ooms) + 1;
                if (flags & FLAG_ROUND_UP > 0) {
                    return scaleDownRoundUp(a, scaleDownBy);
                } else {
                    return scaleDown(a, scaleDownBy);
                }
            } else {
                return a;
            }
        }
    }

    /// Scale an 18 decimal fixed point number to scale 0 (i.e. an integer)
    /// losslessly.
    /// Reverts if the conversion would be lossy.
    /// @param a An 18 decimal fixed point number.
    /// @return `a` scaled to 0 decimals.
    function scaleToIntegerLossless(uint256 a) internal pure returns (uint256) {
        unchecked {
            if (a % FIXED_POINT_ONE != 0) {
                revert ErrScaleDownPrecisionLoss(a);
            }
            return a / FIXED_POINT_ONE;
        }
    }

    /// Detect whether some value is a fixed point decimal or an integer and
    /// convert it to an integer if it is a decimal.
    ///
    /// The detection process assumes that anything greater than or equal to
    /// `FIXED_POINT_ONE` is a fixed point decimal and NOT some large integer.
    ///
    /// The caller is responsible for ensuring that the range of valid integers
    /// never overlaps with the range of valid fixed point decimals that could
    /// be interpreted as integers. I.e. `max` should be less than `1e18`.
    ///
    /// Uses lossless conversion to integer for fixed point decimals, so will
    /// error if decimals are not a multiple of `FIXED_POINT_ONE`.
    ///
    /// @param a The value to convert to an integer.
    /// @param max The maximum value that `a` can be. MUST be less than `1e18`.
    function decimalOrIntToInt(uint256 a, uint256 max) internal pure returns (uint256) {
        if (a >= FIXED_POINT_ONE) {
            a = scaleToIntegerLossless(a);
        }

        if (a > max) {
            revert IntegerOverflow(a, max);
        }

        return a;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {IInterpreterStoreV1} from "./IInterpreterStoreV1.sol";

/// @dev The index of a source within a deployed expression that can be evaluated
/// by an `IInterpreterV1`. MAY be an entrypoint or the index of a source called
/// internally such as by the `call` opcode.
type SourceIndex is uint16;

/// @dev Encoded information about a specific evaluation including the expression
/// address onchain, entrypoint and expected return values.
type EncodedDispatch is uint256;

/// @dev The namespace for state changes as requested by the calling contract.
/// The interpreter MUST apply this namespace IN ADDITION to namespacing by
/// caller etc.
type StateNamespace is uint256;

/// @dev Additional bytes that can be used to configure a single opcode dispatch.
/// Commonly used to specify the number of inputs to a variadic function such
/// as addition or multiplication.
type Operand is uint256;

/// @dev The default state namespace MUST be used when a calling contract has no
/// particular opinion on or need for dynamic namespaces.
StateNamespace constant DEFAULT_STATE_NAMESPACE = StateNamespace.wrap(0);

/// @title IInterpreterV1
/// Interface into a standard interpreter that supports:
///
/// - evaluating `view` logic deployed onchain by an `IExpressionDeployerV1`
/// - receiving arbitrary `uint256[][]` supporting context to be made available
///   to the evaluated logic
/// - handling subsequent state changes in bulk in response to evaluated logic
/// - namespacing state changes according to the caller's preferences to avoid
///   unwanted key collisions
/// - exposing its internal function pointers to support external precompilation
///   of logic for more gas efficient runtime evaluation by the interpreter
///
/// The interface is designed to be stable across many versions and
/// implementations of an interpreter, balancing minimalism with features
/// required for a general purpose onchain interpreted compute environment.
///
/// The security model of an interpreter is that it MUST be resilient to
/// malicious expressions even if they dispatch arbitrary internal function
/// pointers during an eval. The interpreter MAY return garbage or exhibit
/// undefined behaviour or error during an eval, _provided that no state changes
/// are persisted_ e.g. in storage, such that only the caller that specifies the
/// malicious expression can be negatively impacted by the result. In turn, the
/// caller must guard itself against arbitrarily corrupt/malicious reverts and
/// return values from any interpreter that it requests an expression from. And
/// so on and so forth up to the externally owned account (EOA) who signs the
/// transaction and agrees to a specific combination of contracts, expressions
/// and interpreters, who can presumably make an informed decision about which
/// ones to trust to get the job done.
///
/// The state changes for an interpreter are expected to be produces by an `eval`
/// and passed to the `IInterpreterStoreV1` returned by the eval, as-is by the
/// caller, after the caller has had an opportunity to apply their own
/// intermediate logic such as reentrancy defenses against malicious
/// interpreters. The interpreter is free to structure the state changes however
/// it wants but MUST guard against the calling contract corrupting the changes
/// between `eval` and `set`. For example a store could sandbox storage writes
/// per-caller so that a malicious caller can only damage their own state
/// changes, while honest callers respect, benefit from and are protected by the
/// interpreter store's state change handling.
///
/// The two step eval-state model allows eval to be read-only which provides
/// security guarantees for the caller such as no stateful reentrancy, either
/// from the interpreter or some contract interface used by some word, while
/// still allowing for storage writes. As the storage writes happen on the
/// interpreter rather than the caller (c.f. delegate call) the caller DOES NOT
/// need to trust the interpreter, which allows for permissionless selection of
/// interpreters by end users. Delegate call always implies an admin key on the
/// caller because the delegatee contract can write arbitrarily to the state of
/// the delegator, which severely limits the generality of contract composition.
interface IInterpreterV1 {
    /// Exposes the function pointers as `uint16` values packed into a single
    /// `bytes` in the same order as they would be indexed into by opcodes. For
    /// example, if opcode `2` should dispatch function at position `0x1234` then
    /// the start of the returned bytes would be `0xXXXXXXXX1234` where `X` is
    /// a placeholder for the function pointers of opcodes `0` and `1`.
    ///
    /// `IExpressionDeployerV1` contracts use these function pointers to
    /// "compile" the expression into something that an interpreter can dispatch
    /// directly without paying gas to lookup the same at runtime. As the
    /// validity of any integrity check and subsequent dispatch is highly
    /// sensitive to both the function pointers and overall bytecode of the
    /// interpreter, `IExpressionDeployerV1` contracts SHOULD implement guards
    /// against accidentally being deployed onchain paired against an unknown
    /// interpreter. It is very easy for an apparent compatible pairing to be
    /// subtly and critically incompatible due to addition/removal/reordering of
    /// opcodes and compiler optimisations on the interpreter bytecode.
    ///
    /// This MAY return different values during construction vs. all other times
    /// after the interpreter has been successfully deployed onchain. DO NOT rely
    /// on function pointers reported during contract construction.
    function functionPointers() external view returns (bytes memory);

    /// The raison d'etre for an interpreter. Given some expression and per-call
    /// additional contextual data, produce a stack of results and a set of state
    /// changes that the caller MAY OPTIONALLY pass back to be persisted by a
    /// call to `IInterpreterStoreV1.set`.
    /// @param store The storage contract that the returned key/value pairs
    /// MUST be passed to IF the calling contract is in a non-static calling
    /// context. Static calling contexts MUST pass `address(0)`.
    /// @param namespace The state namespace that will be fully qualified by the
    /// interpreter at runtime in order to perform gets on the underlying store.
    /// MUST be the same namespace passed to the store by the calling contract
    /// when sending the resulting key/value items to storage.
    /// @param dispatch All the information required for the interpreter to load
    /// an expression, select an entrypoint and return the values expected by the
    /// caller. The interpreter MAY encode dispatches differently to
    /// `LibEncodedDispatch` but this WILL negatively impact compatibility for
    /// calling contracts that hardcode the encoding logic.
    /// @param context A 2-dimensional array of data that can be indexed into at
    /// runtime by the interpreter. The calling contract is responsible for
    /// ensuring the authenticity and completeness of context data. The
    /// interpreter MUST revert at runtime if an expression attempts to index
    /// into some context value that is not provided by the caller. This implies
    /// that context reads cannot be checked for out of bounds reads at deploy
    /// time, as the runtime context MAY be provided in a different shape to what
    /// the expression is expecting.
    /// Same as `eval` but allowing the caller to specify a namespace under which
    /// the state changes will be applied. The interpeter MUST ensure that keys
    /// will never collide across namespaces, even if, for example:
    ///
    /// - The calling contract is malicious and attempts to craft a collision
    ///   with state changes from another contract
    /// - The expression is malicious and attempts to craft a collision with
    ///   other expressions evaluated by the same calling contract
    ///
    /// A malicious entity MAY have access to significant offchain resources to
    /// attempt to precompute key collisions through brute force. The collision
    /// resistance of namespaces should be comparable or equivalent to the
    /// collision resistance of the hashing algorithms employed by the blockchain
    /// itself, such as the design of `mapping` in Solidity that hashes each
    /// nested key to produce a collision resistant compound key.
    /// @return stack The list of values produced by evaluating the expression.
    /// MUST NOT be longer than the maximum length specified by `dispatch`, if
    /// applicable.
    /// @return kvs A list of pairwise key/value items to be saved in the store.
    function eval(
        IInterpreterStoreV1 store,
        StateNamespace namespace,
        EncodedDispatch dispatch,
        uint256[][] calldata context
    ) external view returns (uint256[] memory stack, uint256[] memory kvs);
}

// SPDX-License-Identifier: CC0
// Alberto Cuesta Cañada, Fiona Kobayashi, fubuloubu, Austin Williams, "EIP-3156: Flash Loans," Ethereum Improvement Proposals, no. 3156, November 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-3156.
pragma solidity ^0.8.18;

/// @dev The ERC3156 spec mandates this hash be returned by `onFlashLoan` if it
/// succeeds.
bytes32 constant ON_FLASH_LOAN_CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan");

interface IERC3156FlashBorrower {
    /**
     * @dev Receive a flash loan.
     * @param initiator The initiator of the loan.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @param fee The additional amount of tokens to repay.
     * @param data Arbitrary data structure, intended to contain user-defined parameters.
     * @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan"
     */
    function onFlashLoan(address initiator, address token, uint256 amount, uint256 fee, bytes calldata data)
        external
        returns (bytes32);
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

// Reexport AuthoringMetaV2 for downstream use.
import {AuthoringMetaV2} from "./deprecated/IParserV1.sol";

interface IParserV2 {
    function parse2(bytes calldata data) external view returns (bytes calldata bytecode);
}

File 42 of 55 : IInterpreterCallerV2.sol
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {IExpressionDeployerV3} from "./IExpressionDeployerV3.sol";
import {IInterpreterStoreV2} from "../IInterpreterStoreV2.sol";
import {IInterpreterV2} from "./IInterpreterV2.sol";

/// Standard struct that can be embedded in ABIs in a consistent format for
/// tooling to read/write. MAY be useful to bundle up the data required to call
/// `IExpressionDeployerV3` but is NOT mandatory.
/// @param deployer Will deploy the expression from sources and constants.
/// @param bytecode Will be deployed to an expression address for use in
/// `Evaluable`.
/// @param constants Will be available to the expression at runtime.
struct EvaluableConfigV3 {
    IExpressionDeployerV3 deployer;
    bytes bytecode;
    uint256[] constants;
}

/// Struct over the return of `IExpressionDeployerV3.deployExpression2`
/// which MAY be more convenient to work with than raw addresses.
/// @param interpreter Will evaluate the expression.
/// @param store Will store state changes due to evaluation of the expression.
/// @param expression Will be evaluated by the interpreter.
struct EvaluableV2 {
    IInterpreterV2 interpreter;
    IInterpreterStoreV2 store;
    address expression;
}

/// Typed embodiment of some context data with associated signer and signature.
/// The signature MUST be over the packed encoded bytes of the context array,
/// i.e. the context array concatenated as bytes without the length prefix, then
/// hashed, then handled as per EIP-191 to produce a final hash to be signed.
///
/// The calling contract (likely with the help of `LibContext`) is responsible
/// for ensuring the authenticity of the signature, but not authorizing _who_ can
/// sign. IN ADDITION to authorisation of the signer to known-good entities the
/// expression is also responsible for:
///
/// - Enforcing the context is the expected data (e.g. with a domain separator)
/// - Tracking and enforcing nonces if signed contexts are only usable one time
/// - Tracking and enforcing uniqueness of signed data if relevant
/// - Checking and enforcing expiry times if present and relevant in the context
/// - Many other potential constraints that expressions may want to enforce
///
/// EIP-1271 smart contract signatures are supported in addition to EOA
/// signatures via. the Open Zeppelin `SignatureChecker` library, which is
/// wrapped by `LibContext.build`. As smart contract signatures are checked
/// onchain they CAN BE REVOKED AT ANY MOMENT as the smart contract can simply
/// return `false` when it previously returned `true`.
///
/// @param signer The account that produced the signature for `context`. The
/// calling contract MUST authenticate that the signer produced the signature.
/// @param context The signed data in a format that can be merged into a
/// 2-dimensional context matrix as-is.
/// @param signature The cryptographic signature for `context`. The calling
/// contract MUST authenticate that the signature is valid for the `signer` and
/// `context`.
struct SignedContextV1 {
    // The ordering of these fields is important and used in assembly offset
    // calculations and hashing.
    address signer;
    uint256[] context;
    bytes signature;
}

uint256 constant SIGNED_CONTEXT_SIGNER_OFFSET = 0;
uint256 constant SIGNED_CONTEXT_CONTEXT_OFFSET = 0x20;
uint256 constant SIGNED_CONTEXT_SIGNATURE_OFFSET = 0x40;

/// @title IInterpreterCallerV2
/// @notice A contract that calls an `IInterpreterV1` via. `eval`. There are near
/// zero requirements on a caller other than:
///
/// - Emit some meta about itself upon construction so humans know what the
///   contract does
/// - Provide the context, which can be built in a standard way by `LibContext`
/// - Handle the stack array returned from `eval`
/// - OPTIONALLY emit the `Context` event
/// - OPTIONALLY set state on the `IInterpreterStoreV1` returned from eval.
interface IInterpreterCallerV2 {
    /// Calling contracts SHOULD emit `Context` before calling `eval` if they
    /// are able. Notably `eval` MAY be called within a static call which means
    /// that events cannot be emitted, in which case this does not apply. It MAY
    /// NOT be useful to emit this multiple times for several eval calls if they
    /// all share a common context, in which case a single emit is sufficient.
    /// @param sender `msg.sender` building the context.
    /// @param context The context that was built.
    event Context(address sender, uint256[][] context);
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {IInterpreterStoreV2} from "../IInterpreterStoreV2.sol";
import {IInterpreterV2} from "./IInterpreterV2.sol";

string constant IERC1820_NAME_IEXPRESSION_DEPLOYER_V3 = "IExpressionDeployerV3";

/// @title IExpressionDeployerV3
/// @notice Companion to `IInterpreterV2` responsible for onchain static code
/// analysis and deploying expressions. Each `IExpressionDeployerV3` is tightly
/// coupled at the bytecode level to some interpreter that it knows how to
/// analyse and deploy expressions for. The expression deployer can perform an
/// integrity check "dry run" of candidate source code for the intepreter. The
/// critical analysis/transformation includes:
///
/// - Enforcement of no out of bounds memory reads/writes
/// - Calculation of memory required to eval the stack with a single allocation
/// - Replacing index based opcodes with absolute interpreter function pointers
/// - Enforcement that all opcodes and operands used exist and are valid
///
/// This analysis is highly sensitive to the specific implementation and position
/// of all opcodes and function pointers as compiled into the interpreter. This
/// is what makes the coupling between an interpreter and expression deployer
/// so tight. Ideally all responsibilities would be handled by a single contract
/// but this introduces code size issues quickly by roughly doubling the compiled
/// logic of each opcode (half for the integrity check and half for evaluation).
///
/// Interpreters MUST assume that expression deployers are malicious and fail
/// gracefully if the integrity check is corrupt/bypassed and/or function
/// pointers are incorrect, etc. i.e. the interpreter MUST always return a stack
/// from `eval` in a read only way or error. I.e. it is the expression deployer's
/// responsibility to do everything it can to prevent undefined behaviour in the
/// interpreter, and the interpreter's responsibility to handle the expression
/// deployer completely failing to do so.
interface IExpressionDeployerV3 {
    /// The config of the deployed expression including uncompiled sources. MUST
    /// be emitted after the config passes the integrity check.
    /// @param sender The caller of `deployExpression2`.
    /// @param bytecode As per `IExpressionDeployerV3.deployExpression2` inputs.
    /// @param constants As per `IExpressionDeployerV3.deployExpression2` inputs.
    event NewExpression(address sender, bytes bytecode, uint256[] constants);

    /// The address of the deployed expression. MUST be emitted once the
    /// expression can be loaded and deserialized into an evaluable interpreter
    /// state.
    /// @param sender The caller of `deployExpression2`.
    /// @param interpreter As per `IExpressionDeployerV3.deployExpression2` return.
    /// @param store As per `IExpressionDeployerV3.deployExpression2` return.
    /// @param expression As per `IExpressionDeployerV3.deployExpression2` return.
    /// @param io As per `IExpressionDeployerV3.deployExpression2` return.
    event DeployedExpression(
        address sender, IInterpreterV2 interpreter, IInterpreterStoreV2 store, address expression, bytes io
    );

    /// This is the literal InterpreterOpMeta bytes to be used offchain to make
    /// sense of the opcodes in this interpreter deployment, as a human. For
    /// formats like json that make heavy use of boilerplate, repetition and
    /// whitespace, some kind of compression is recommended.
    /// The DISPair is a pairing of:
    /// - Deployer (this contract)
    /// - Interpreter
    /// - Store
    /// - Parser
    ///
    /// @param sender The `msg.sender` providing the op meta.
    /// @param interpreter The interpreter the deployer believes it is qualified
    /// to perform integrity checks on behalf of.
    /// @param store The interpreter store the deployer believes is compatible
    /// with the interpreter.
    /// @param parser The parser the deployer believes is compatible with the
    /// interpreter.
    /// @param meta The raw binary data of the construction meta. Maybe
    /// compressed data etc. and is intended for offchain consumption.
    event DISPair(address sender, address interpreter, address store, address parser, bytes meta);

    /// Expressions are expected to be deployed onchain as immutable contract
    /// code with a first class address like any other contract or account.
    /// Technically this is optional in the sense that all the tools required to
    /// eval some expression and define all its opcodes are available as
    /// libraries.
    ///
    /// In practise there are enough advantages to deploying the sources directly
    /// onchain as contract data and loading them from the interpreter at eval:
    ///
    /// - Loading and storing binary data is gas efficient as immutable contract
    ///   data
    /// - Expressions need to be immutable between their deploy time integrity
    ///   check and runtime evaluation
    /// - Passing the address of an expression through calldata to an interpreter
    ///   is cheaper than passing an entire expression through calldata
    /// - Conceptually a very simple approach, even if implementations like
    ///   SSTORE2 are subtle under the hood
    ///
    /// The expression deployer MUST perform an integrity check of the source
    /// code before it puts the expression onchain at a known address. The
    /// integrity check MUST at a minimum (it is free to do additional static
    /// analysis) calculate the memory required to be allocated for the stack in
    /// total, and that no out of bounds memory reads/writes occur within this
    /// stack. A simple example of an invalid source would be one that pushes one
    /// value to the stack then attempts to pops two values, clearly we cannot
    /// remove more values than we added. The `IExpressionDeployerV3` MUST revert
    /// in the case of any integrity failure, all integrity checks MUST pass in
    /// order for the deployment to complete.
    ///
    /// Once the integrity check is complete the `IExpressionDeployerV3` MUST do
    /// any additional processing required by its paired interpreter.
    /// For example, the `IExpressionDeployerV3` MAY NEED to replace the indexed
    /// opcodes in the `ExpressionConfig` sources with real function pointers
    /// from the corresponding interpreter.
    ///
    /// The caller MUST check the `io` returned by this function to determine
    /// the number of inputs and outputs for each source are within the bounds
    /// of the caller's expectations.
    ///
    /// @param bytecode Bytecode verbatim. Exactly how the bytecode is structured
    /// is up to the deployer and interpreter. The deployer MUST NOT modify the
    /// bytecode in any way. The interpreter MUST NOT assume anything about the
    /// bytecode other than that it is valid according to the interpreter's
    /// integrity checks. It is assumed that the bytecode will be produced from
    /// a human friendly string via. `IParserV1.parse` but this is not required
    /// if the caller has some other means to prooduce valid bytecode.
    /// @param constants Constants verbatim. Constants are provided alongside
    /// sources rather than inline as it allows us to avoid variable length
    /// opcodes and can be more memory efficient if the same constant is
    /// referenced several times from the sources.
    /// @return interpreter The interpreter the deployer believes it is qualified
    /// to perform integrity checks on behalf of.
    /// @return store The interpreter store the deployer believes is compatible
    /// with the interpreter.
    /// @return expression The address of the deployed onchain expression. MUST
    /// be valid according to all integrity checks the deployer is aware of.
    /// @return io Binary data where each 2 bytes input and output counts for
    /// each source of the bytecode. MAY simply be copied verbatim from the
    /// relevant bytes in the bytecode if they exist and integrity checks
    /// guarantee that the bytecode is valid.
    function deployExpression2(bytes calldata bytecode, uint256[] calldata constants)
        external
        returns (IInterpreterV2 interpreter, IInterpreterStoreV2 store, address expression, bytes calldata io);
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {IERC3156FlashLender} from "../../ierc3156/IERC3156FlashLender.sol";
import {EvaluableConfig, Evaluable} from "rain.interpreter.interface/interface/deprecated/IInterpreterCallerV1.sol";
import {
    SignedContextV1,
    IInterpreterCallerV2
} from "rain.interpreter.interface/interface/deprecated/IInterpreterCallerV2.sol";
import {IExpressionDeployerV2} from "rain.interpreter.interface/interface/deprecated/IExpressionDeployerV2.sol";

/// Configuration for a deposit. All deposits are processed by and for
/// `msg.sender` so the vaults are unambiguous here.
/// @param token The token to deposit.
/// @param vaultId The vault ID for the token to deposit.
/// @param amount The amount of the token to deposit.
struct DepositConfig {
    address token;
    uint256 vaultId;
    uint256 amount;
}

/// Configuration for a withdrawal. All withdrawals are processed by and for
/// `msg.sender` so the vaults are unambiguous here.
/// @param token The token to withdraw.
/// @param vaultId The vault ID for the token to withdraw.
/// @param amount The amount of the token to withdraw.
struct WithdrawConfig {
    address token;
    uint256 vaultId;
    uint256 amount;
}

/// Configuration for a single input or output on an `Order`.
/// @param token The token to either send from the owner as an output or receive
/// from the counterparty to the owner as an input. The tokens are not moved
/// during an order, only internal vault balances are updated, until a separate
/// withdraw step.
/// @param decimals The decimals to use for internal scaling calculations for
/// `token`. This is provided directly in IO to save gas on external lookups and
/// to respect the ERC20 spec that mandates NOT assuming or using the `decimals`
/// method for onchain calculations. Ostensibly the decimals exists so that all
/// calculate order entrypoints can treat amounts and ratios as 18 decimal fixed
/// point values. Order max amounts MUST be rounded down and IO ratios rounded up
/// to compensate for any loss of precision during decimal rescaling.
/// @param vaultId The vault ID that tokens will move into if this is an input
/// or move out from if this is an output.
struct IO {
    address token;
    uint8 decimals;
    uint256 vaultId;
}

/// Config the order owner may provide to define their order. The `msg.sender`
/// that adds an order cannot modify the owner nor bypass the integrity check of
/// the expression deployer that they specify. However they MAY specify a
/// deployer with a corrupt integrity check, so counterparties and clearers MUST
/// check the DISpair of the order and avoid untrusted pairings.
/// @param validInputs As per `validInputs` on the `Order`.
/// @param validOutputs As per `validOutputs` on the `Order`.
/// @param evaluableConfig Standard `EvaluableConfig` used to produce the
/// `Evaluable` on the order.
/// @param meta Arbitrary bytes that will NOT be used in the order evaluation
/// but MUST be emitted as a Rain `MetaV1` when the order is placed so can be
/// used by offchain processes.
struct OrderConfig {
    IO[] validInputs;
    IO[] validOutputs;
    EvaluableConfig evaluableConfig;
    bytes meta;
}

/// Defines a fully deployed order ready to evaluate by Orderbook.
/// @param owner The owner of the order is the `msg.sender` that added the order.
/// @param handleIO true if there is a "handle IO" entrypoint to run. If false
/// the order book MAY skip calling the interpreter to save gas.
/// @param evaluable Standard `Evaluable` with entrypoints for both
/// "calculate order" and "handle IO". The latter MAY be empty bytes, in which
/// case it will be skipped at runtime to save gas.
/// @param validInputs A list of input tokens that are economically equivalent
/// for the purpose of processing this order. Inputs are relative to the order
/// so these tokens will be sent to the owners vault.
/// @param validOutputs A list of output tokens that are economically equivalent
/// for the purpose of processing this order. Outputs are relative to the order
/// so these tokens will be sent from the owners vault.
struct Order {
    address owner;
    bool handleIO;
    Evaluable evaluable;
    IO[] validInputs;
    IO[] validOutputs;
}

/// Config for a list of orders to take sequentially as part of a `takeOrders`
/// call.
/// @param output Output token from the perspective of the order taker.
/// @param input Input token from the perspective of the order taker.
/// @param minimumInput Minimum input from the perspective of the order taker.
/// @param maximumInput Maximum input from the perspective of the order taker.
/// @param maximumIORatio Maximum IO ratio as calculated by the order being
/// taken. The input is from the perspective of the order so higher ratio means
/// worse deal for the order taker.
/// @param orders Ordered list of orders that will be taken until the limit is
/// hit. Takers are expected to prioritise orders that appear to be offering
/// better deals i.e. lower IO ratios. This prioritisation and sorting MUST
/// happen offchain, e.g. via. some simulator.
struct TakeOrdersConfig {
    address output;
    address input;
    uint256 minimumInput;
    uint256 maximumInput;
    uint256 maximumIORatio;
    TakeOrderConfig[] orders;
}

/// Config for an individual take order from the overall list of orders in a
/// call to `takeOrders`.
/// @param order The order being taken this iteration.
/// @param inputIOIndex The index of the input token in `order` to match with the
/// take order output.
/// @param outputIOIndex The index of the output token in `order` to match with
/// the take order input.
/// @param signedContext Optional additional signed context relevant to the
/// taken order.
struct TakeOrderConfig {
    Order order;
    uint256 inputIOIndex;
    uint256 outputIOIndex;
    SignedContextV1[] signedContext;
}

/// Additional config to a `clear` that allows two orders to be fully matched to
/// a specific token moment. Also defines the bounty for the clearer.
/// @param aliceInputIOIndex The index of the input token in order A.
/// @param aliceOutputIOIndex The index of the output token in order A.
/// @param bobInputIOIndex The index of the input token in order B.
/// @param bobOutputIOIndex The index of the output token in order B.
/// @param aliceBountyVaultId The vault ID that the bounty from order A should
/// move to for the clearer.
/// @param bobBountyVaultId The vault ID that the bounty from order B should move
/// to for the clearer.
struct ClearConfig {
    uint256 aliceInputIOIndex;
    uint256 aliceOutputIOIndex;
    uint256 bobInputIOIndex;
    uint256 bobOutputIOIndex;
    uint256 aliceBountyVaultId;
    uint256 bobBountyVaultId;
}

/// Summary of the vault state changes due to clearing an order. NOT the state
/// changes sent to the interpreter store, these are the LOCAL CHANGES in vault
/// balances. Note that the difference in inputs/outputs overall between the
/// counterparties is the bounty paid to the entity that cleared the order.
/// @param aliceOutput Amount of counterparty A's output token that moved out of
/// their vault.
/// @param bobOutput Amount of counterparty B's output token that moved out of
/// their vault.
/// @param aliceInput Amount of counterparty A's input token that moved into
/// their vault.
/// @param bobInput Amount of counterparty B's input token that moved into their
/// vault.
struct ClearStateChange {
    uint256 aliceOutput;
    uint256 bobOutput;
    uint256 aliceInput;
    uint256 bobInput;
}

/// @title IOrderBookV2
/// @notice An orderbook that deploys _strategies_ represented as interpreter
/// expressions rather than individual orders. The order book contract itself
/// behaves similarly to an `ERC4626` vault but with much more fine grained
/// control over how tokens are allocated and moved internally by their owners,
/// and without any concept of "shares". Token owners MAY deposit and withdraw
/// their tokens under arbitrary vault IDs on a per-token basis, then define
/// orders that specify how tokens move between vaults according to an expression.
/// The expression returns a maximum amount and a token input/output ratio from
/// the perpective of the order. When two expressions intersect, as in their
/// ratios are the inverse of each other, then tokens can move between vaults.
///
/// For example, consider order A with input TKNA and output TKNB with a constant
/// ratio of 100:1. This order in isolation has no ability to move tokens. If
/// an order B appears with input TKNB and output TKNA and a ratio of 1:100 then
/// this is a perfect match with order A. In this case 100 TKNA will move from
/// order B to order A and 1 TKNB will move from order A to order B.
///
/// IO ratios are always specified as input:output and are 18 decimal fixed point
/// values. The maximum amount that can be moved in the current clearance is also
/// set by the order expression as an 18 decimal fixed point value.
///
/// Typically orders will not clear when their match is exactly 1:1 as the
/// clearer needs to pay gas to process the match. Each order will get exactly
/// the ratio it calculates when it does clear so if there is _overlap_ in the
/// ratios then the clearer keeps the difference. In our above example, consider
/// order B asking a ratio of 1:110 instead of 1:100. In this case 100 TKNA will
/// move from order B to order A and 10 TKNA will move to the clearer's vault and
/// 1 TKNB will move from order A to order B. In the case of fixed prices this is
/// not very interesting as order B could more simply take order A directly for
/// cheaper rather than involving a third party. Indeed, Orderbook supports a
/// direct "take orders" method that works similar to a "market buy". In the case
/// of dynamic expression based ratios, it allows both order A and order B to
/// clear non-interactively according to their strategy, trading off active
/// management, dealing with front-running, MEV, etc. for zero-gas and
/// exact-ratio clearance.
///
/// The general invariant for clearing and take orders is:
///
/// ```
/// ratioA = InputA / OutputA
/// ratioB = InputB / OutputB
/// ratioA * ratioB = ( InputA * InputB ) / ( OutputA * OutputB )
/// OutputA >= InputB
/// OutputB >= InputA
///
/// ∴ ratioA * ratioB <= 1
/// ```
///
/// Orderbook is `IERC3156FlashLender` compliant with a 0 fee flash loan
/// implementation to allow external liquidity from other onchain DEXes to match
/// against orderbook expressions. All deposited tokens across all vaults are
/// available for flashloan, the flashloan MAY BE REPAID BY CALLING TAKE ORDER
/// such that Orderbook's liability to its vaults is decreased by an incoming
/// trade from the flashloan borrower. See `ZeroExOrderBookFlashBorrower` for
/// an example of how this works in practise.
///
/// Orderbook supports many to many input/output token relationship, for example
/// some order can specify an array of stables it would be willing to accept in
/// return for some ETH. This removes the need for a combinatorial explosion of
/// order strategies between like assets but introduces the issue of token
/// decimal handling. End users understand that "one" USDT is roughly equal to
/// "one" DAI, but onchain this is incorrect by _12 orders of magnitude_. This
/// is because "one" DAI is `1e18` tokens and "one" USDT is `1e6` tokens. The
/// orderbook is allowing orders to deploy expressions that define _economic
/// equivalence_ but this doesn't map 1:1 with numeric equivalence in a many to
/// many setup behind token decimal convensions. The solution is to require that
/// end users who place orders provide the decimals of each token they include
/// in their valid IO lists, and to calculate all amounts and ratios in their
/// expressions _as though they were 18 decimal fixed point values_. Orderbook
/// will then automatically rescale the expression values before applying the
/// final vault movements. If an order provides the "wrong" decimal values for
/// some token then it will simply calculate its own ratios and amounts
/// incorrectly which will either lead to no matching orders or a very bad trade
/// for the order owner. There is no way that misrepresenting decimals can attack
/// some other order by a counterparty. Orderbook DOES NOT read decimals from
/// tokens onchain because A. this would be gas for an external call to a cold
/// token contract and B. the ERC20 standard specifically states NOT to read
/// decimals from the interface onchain.
///
/// Token amounts and ratios returned by calculate order MUST be 18 decimal fixed
/// point values. Token amounts input to handle IO MUST be the exact absolute
/// values that move between the vaults, i.e. NOT rescaled to 18 decimals. The
/// author of the handle IO expression MUST use the token decimals and amounts to
/// rescale themselves if they want that logic, notably the expression author
/// will need to specify the desired rounding behaviour in the rescaling process.
///
/// When two orders clear there are NO TOKEN MOVEMENTS, only internal vault
/// balances are updated from the input and output vaults. Typically this results
/// in less gas per clear than calling external token transfers and also avoids
/// issues with reentrancy, allowances, external balances etc. This also means
/// that REBASING TOKENS AND TOKENS WITH DYNAMIC BALANCE ARE NOT SUPPORTED.
/// Orderbook ONLY WORKS IF TOKEN BALANCES ARE 1:1 WITH ADDITION/SUBTRACTION PER
/// VAULT MOVEMENT.
///
/// Dust due to rounding errors always favours the order. Output max is rounded
/// down and IO ratios are rounded up. Input and output amounts are always
/// converted to absolute values before applying to vault balances such that
/// orderbook always retains fully collateralised inventory of underlying token
/// balances to support withdrawals, with the caveat that dynamic token balanes
/// are not supported.
///
/// When an order clears it is NOT removed. Orders remain active until the owner
/// deactivates them. This is gas efficient as order owners MAY deposit more
/// tokens in a vault with an order against it many times and the order strategy
/// will continue to be clearable according to its expression. As vault IDs are
/// `uint256` values there are effectively infinite possible vaults for any token
/// so there is no limit to how many active orders any address can have at one
/// time. This also allows orders to be daisy chained arbitrarily where output
/// vaults for some order are the input vaults for some other order.
///
/// Expression storage is namespaced by order owner, so gets and sets are unique
/// to each onchain address. Order owners MUST TAKE CARE not to override their
/// storage sets globally across all their orders, which they can do most simply
/// by hashing the order hash into their get/set keys inside the expression. This
/// gives maximum flexibility for shared state across orders without allowing
/// order owners to attack and overwrite values stored by orders placed by their
/// counterparty.
///
/// Note that each order specifies its own interpreter and deployer so the
/// owner is responsible for not corrupting their own calculations with bad
/// interpreters. This also means the Orderbook MUST assume the interpreter, and
/// notably the interpreter's store, is malicious and guard against reentrancy
/// etc.
///
/// As Orderbook supports any expression that can run on any `IInterpreterV1` and
/// counterparties are available to the order, order strategies are free to
/// implement KYC/membership, tracking, distributions, stock, buybacks, etc. etc.
interface IOrderBookV2 is IERC3156FlashLender, IInterpreterCallerV2 {
    /// Some tokens have been deposited to a vault.
    /// @param sender `msg.sender` depositing tokens. Delegated deposits are NOT
    /// supported.
    /// @param config All config sent to the `deposit` call.
    event Deposit(address sender, DepositConfig config);

    /// Some tokens have been withdrawn from a vault.
    /// @param sender `msg.sender` withdrawing tokens. Delegated withdrawals are
    /// NOT supported.
    /// @param config All config sent to the `withdraw` call.
    /// @param amount The amount of tokens withdrawn, can be less than the
    /// config amount if the vault does not have the funds available to cover
    /// the config amount. For example an active order might move tokens before
    /// the withdraw completes.
    event Withdraw(address sender, WithdrawConfig config, uint256 amount);

    /// An order has been added to the orderbook. The order is permanently and
    /// always active according to its expression until/unless it is removed.
    /// @param sender `msg.sender` adding the order and is owner of the order.
    /// @param expressionDeployer The expression deployer that ran the integrity
    /// check for this order. This is NOT included in the `Order` itself but is
    /// important for offchain processes to ignore untrusted deployers before
    /// interacting with them.
    /// @param order The newly added order. MUST be handed back as-is when
    /// clearing orders and contains derived information in addition to the order
    /// config that was provided by the order owner.
    /// @param orderHash The hash of the order as it is recorded onchain. Only
    /// the hash is stored in Orderbook storage to avoid paying gas to store the
    /// entire order.
    event AddOrder(address sender, IExpressionDeployerV2 expressionDeployer, Order order, uint256 orderHash);

    /// An order has been removed from the orderbook. This effectively
    /// deactivates it. Orders can be added again after removal.
    /// @param sender `msg.sender` removing the order and is owner of the order.
    /// @param order The removed order.
    /// @param orderHash The hash of the removed order.
    event RemoveOrder(address sender, Order order, uint256 orderHash);

    /// Some order has been taken by `msg.sender`. This is the same as them
    /// placing inverse orders then immediately clearing them all, but costs less
    /// gas and is more convenient and reliable. Analogous to a market buy
    /// against the specified orders. Each order that is matched within a the
    /// `takeOrders` loop emits its own individual event.
    /// @param sender `msg.sender` taking the orders.
    /// @param config All config defining the orders to attempt to take.
    /// @param input The input amount from the perspective of sender.
    /// @param output The output amount from the perspective of sender.
    event TakeOrder(address sender, TakeOrderConfig config, uint256 input, uint256 output);

    /// Emitted when attempting to match an order that either never existed or
    /// was removed. An event rather than an error so that we allow attempting
    /// many orders in a loop and NOT rollback on "best effort" basis to clear.
    /// @param sender `msg.sender` clearing the order that wasn't found.
    /// @param owner Owner of the order that was not found.
    /// @param orderHash Hash of the order that was not found.
    event OrderNotFound(address sender, address owner, uint256 orderHash);

    /// Emitted when an order evaluates to a zero amount. An event rather than an
    /// error so that we allow attempting many orders in a loop and NOT rollback
    /// on a "best effort" basis to clear.
    /// @param sender `msg.sender` clearing the order that had a 0 amount.
    /// @param owner Owner of the order that evaluated to a 0 amount.
    /// @param orderHash Hash of the order that evaluated to a 0 amount.
    event OrderZeroAmount(address sender, address owner, uint256 orderHash);

    /// Emitted when an order evaluates to a ratio exceeding the counterparty's
    /// maximum limit. An error rather than an error so that we allow attempting
    /// many orders in a loop and NOT rollback on a "best effort" basis to clear.
    /// @param sender `msg.sender` clearing the order that had an excess ratio.
    /// @param owner Owner of the order that had an excess ratio.
    /// @param orderHash Hash of the order that had an excess ratio.
    event OrderExceedsMaxRatio(address sender, address owner, uint256 orderHash);

    /// Emitted before two orders clear. Covers both orders and includes all the
    /// state before anything is calculated.
    /// @param sender `msg.sender` clearing both orders.
    /// @param alice One of the orders.
    /// @param bob The other order.
    /// @param clearConfig Additional config required to process the clearance.
    event Clear(address sender, Order alice, Order bob, ClearConfig clearConfig);

    /// Emitted after two orders clear. Includes all final state changes in the
    /// vault balances, including the clearer's vaults.
    /// @param sender `msg.sender` clearing the order.
    /// @param clearStateChange The final vault state changes from the clearance.
    event AfterClear(address sender, ClearStateChange clearStateChange);

    /// Get the current balance of a vault for a given owner, token and vault ID.
    /// @param owner The owner of the vault.
    /// @param token The token the vault is for.
    /// @param id The vault ID to read.
    /// @return balance The current balance of the vault.
    function vaultBalance(address owner, address token, uint256 id) external view returns (uint256 balance);

    /// `msg.sender` deposits tokens according to config. The config specifies
    /// the vault to deposit tokens under. Delegated depositing is NOT supported.
    /// Depositing DOES NOT mint shares (unlike ERC4626) so the overall vaulted
    /// experience is much simpler as there is always a 1:1 relationship between
    /// deposited assets and vault balances globally and individually. This
    /// mitigates rounding/dust issues, speculative behaviour on derived assets,
    /// possible regulatory issues re: whether a vault share is a security, code
    /// bloat on the vault, complex mint/deposit/withdraw/redeem 4-way logic,
    /// the need for preview functions, etc. etc.
    /// At the same time, allowing vault IDs to be specified by the depositor
    /// allows much more granular and direct control over token movements within
    /// Orderbook than either ERC4626 vault shares or mere contract-level ERC20
    /// allowances can facilitate.
    /// @param config All config for the deposit.
    function deposit(DepositConfig calldata config) external;

    /// Allows the sender to withdraw any tokens from their own vaults. If the
    /// withrawer has an active flash loan debt denominated in the same token
    /// being withdrawn then Orderbook will merely reduce the debt and NOT send
    /// the amount of tokens repaid to the flashloan debt.
    /// @param config All config required to withdraw. Notably if the amount
    /// is less than the current vault balance then the vault will be cleared
    /// to 0 rather than the withdraw transaction reverting.
    function withdraw(WithdrawConfig calldata config) external;

    /// Given an order config, deploys the expression and builds the full `Order`
    /// for the config, then records it as an active order. Delegated adding an
    /// order is NOT supported. The `msg.sender` that adds an order is ALWAYS
    /// the owner and all resulting vault movements are their own.
    /// @param config All config required to build an `Order`.
    function addOrder(OrderConfig calldata config) external;

    /// Order owner can remove their own orders. Delegated order removal is NOT
    /// supported and will revert. Removing an order multiple times or removing
    /// an order that never existed are valid, the event will be emitted and the
    /// transaction will complete with that order hash definitely, redundantly
    /// not live.
    /// @param order The `Order` data exactly as it was added.
    function removeOrder(Order calldata order) external;

    /// Allows `msg.sender` to attempt to fill a list of orders in sequence
    /// without needing to place their own order and clear them. This works like
    /// a market buy but against a specific set of orders. Every order will
    /// looped over and calculated individually then filled maximally until the
    /// request input is reached for the `msg.sender`. The `msg.sender` is
    /// responsible for selecting the best orders at the time according to their
    /// criteria and MAY specify a maximum IO ratio to guard against an order
    /// spiking the ratio beyond what the `msg.sender` expected and is
    /// comfortable with. As orders may be removed and calculate their ratios
    /// dynamically, all issues fulfilling an order other than misconfiguration
    /// by the `msg.sender` are no-ops and DO NOT revert the transaction. This
    /// allows the `msg.sender` to optimistically provide a list of orders that
    /// they aren't sure will completely fill at a good price, and fallback to
    /// more reliable orders further down their list. Misconfiguration such as
    /// token mismatches are errors that revert as this is known and static at
    /// all times to the `msg.sender` so MUST be provided correctly. `msg.sender`
    /// MAY specify a minimum input that MUST be reached across all orders in the
    /// list, otherwise the transaction will revert, this MAY be set to zero.
    ///
    /// Exactly like withdraw, if there is an active flash loan for `msg.sender`
    /// they will have their outstanding loan reduced by the final input amount
    /// preferentially before sending any tokens. Notably this allows arb bots
    /// implemented as flash loan borrowers to connect orders against external
    /// liquidity directly by paying back the loan with a `takeOrders` call and
    /// outputting the result of the external trade.
    ///
    /// Rounding errors always favour the order never the `msg.sender`.
    ///
    /// @param config The constraints and list of orders to take, orders are
    /// processed sequentially in order as provided, there is NO ATTEMPT onchain
    /// to predict/filter/sort these orders other than evaluating them as
    /// provided. Inputs and outputs are from the perspective of `msg.sender`
    /// except for values specified by the orders themselves which are the from
    /// the perspective of that order.
    /// @return totalInput Total tokens sent to `msg.sender`, taken from order
    /// vaults processed.
    /// @return totalOutput Total tokens taken from `msg.sender` and distributed
    /// between vaults.
    function takeOrders(TakeOrdersConfig calldata config) external returns (uint256 totalInput, uint256 totalOutput);

    /// Allows `msg.sender` to match two live orders placed earlier by
    /// non-interactive parties and claim a bounty in the process. The clearer is
    /// free to select any two live orders on the order book for matching and as
    /// long as they have compatible tokens, ratios and amounts, the orders will
    /// clear. Clearing the orders DOES NOT remove them from the orderbook, they
    /// remain live until explicitly removed by their owner. Even if the input
    /// vault balances are completely emptied, the orders remain live until
    /// removed. This allows order owners to deploy a strategy over a long period
    /// of time and periodically top up the input vaults. Clearing two orders
    /// from the same owner is disallowed.
    ///
    /// Any mismatch in the ratios between the two orders will cause either more
    /// inputs than there are available outputs (transaction will revert) or less
    /// inputs than there are available outputs. In the latter case the excess
    /// outputs are given to the `msg.sender` of clear, to the vaults they
    /// specify in the clear config. This not only incentivises "automatic" clear
    /// calls for both alice and bob, but incentivises _prioritising greater
    /// ratio differences_ with a larger bounty. The second point is important
    /// because it implicitly prioritises orders that are further from the
    /// current market price, thus putting constant increasing pressure on the
    /// entire system the further it drifts from the norm, no matter how esoteric
    /// the individual order expressions and sizings might be.
    ///
    /// All else equal there are several factors that would impact how reliably
    /// some order clears relative to the wider market, such as:
    ///
    /// - Bounties are effectively percentages of cleared amounts so larger
    ///   orders have larger bounties and cover gas costs more easily
    /// - High gas on the network means that orders are harder to clear
    ///   profitably so the negative spread of the ratios will need to be larger
    /// - Complex and stateful expressions cost more gas to evalulate so the
    ///   negative spread will need to be larger
    /// - Erratic behavior of the order owner could reduce the willingness of
    ///   third parties to interact if it could result in wasted gas due to
    ///   orders suddently being removed before clearance etc.
    /// - Dynamic and highly volatile words used in the expression could be
    ///   ignored or low priority by clearers who want to be sure that they can
    ///   accurately predict the ratios that they include in their clearance
    /// - Geopolitical issues such as sanctions and regulatory restrictions could
    ///   cause issues for certain owners and clearers
    ///
    /// @param alice Some order to clear.
    /// @param bob Another order to clear.
    /// @param clearConfig Additional configuration for the clearance such as
    /// how to handle the bounty payment for the `msg.sender`.
    /// @param aliceSignedContext Optional signed context that is relevant to A.
    /// @param bobSignedContext Optional signed context that is relevant to B.
    function clear(
        Order memory alice,
        Order memory bob,
        ClearConfig calldata clearConfig,
        SignedContextV1[] memory aliceSignedContext,
        SignedContextV1[] memory bobSignedContext
    ) external;
}

File 45 of 55 : ErrUint256Array.sol
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.25;

/// Thrown if a truncated length is longer than the array being truncated. It is
/// not possible to truncate something and increase its length as the memory
/// region after the array MAY be allocated for something else already.
error OutOfBoundsTruncate(uint256 arrayLength, uint256 truncatedLength);

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC1271 standard signature validation method for
 * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
 *
 * _Available since v4.1._
 */
interface IERC1271 {
    /**
     * @dev Should return whether the signature provided is valid for the provided data
     * @param hash      Hash of the data to be signed
     * @param signature Signature byte array associated with _data
     */
    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

import "./math/Math.sol";
import "./math/SignedMath.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toString(int256 value) internal pure returns (string memory) {
        return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

File 48 of 55 : FixedPointDecimalConstants.sol
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.25;

/// @dev The scale of all fixed point math. This is adopting the conventions of
/// both ETH (wei) and most ERC20 tokens, so is hopefully uncontroversial.
uint256 constant FIXED_POINT_DECIMALS = 18;

/// @dev Value of "one" for fixed point math.
uint256 constant FIXED_POINT_ONE = 1e18;

/// @dev Calculations MUST round up.
uint256 constant FLAG_ROUND_UP = 1;

/// @dev Calculations MUST saturate NOT overflow.
uint256 constant FLAG_SATURATE = 1 << 1;

/// @dev Flags MUST NOT exceed this value.
uint256 constant FLAG_MAX_INT = FLAG_SATURATE | FLAG_ROUND_UP;

/// @dev Can't represent this many OOMs of decimals in `uint256`.
uint256 constant OVERFLOW_RESCALE_OOMS = 78;

/// @dev The maximum value that an integer can be without being misinterpreted
/// as a fixed point decimal, for the purposes of `decimalOrIntToInt`.
uint256 constant DECIMAL_MAX_SAFE_INT = 1e18 - 1;

/// @dev The mathematical constant e, scaled to `FIXED_POINT_DECIMALS` decimals.
/// https://en.wikipedia.org/wiki/E_(mathematical_constant)
uint256 constant FIXED_POINT_E = 2.718281828459045235e18;

File 49 of 55 : ErrScale.sol
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.25;

/// @dev Thrown when downscaling would result in precision loss in a lossless
/// conversion.
/// @param a The value that would lose precision.
error ErrScaleDownPrecisionLoss(uint256 a);

/// Thrown when an integer is too large to fit in the range allowed for it.
/// @param integer The integer that is too large.
/// @param max The maximum value that the integer can be.
error IntegerOverflow(uint256 integer, uint256 max);

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

struct AuthoringMeta {
    // `word` is referenced directly in assembly so don't move the field.
    bytes32 word;
    uint8 operandParserOffset;
    string description;
}

/// Identical to AuthoringMeta but without operandParserOffset.
struct AuthoringMetaV2 {
    // `word` is referenced directly in assembly so don't move the field. It MUST
    // be the first item.
    bytes32 word;
    string description;
}

interface IParserV1 {
    /// Parses a Rainlang string into an evaluable expression. MUST be
    /// deterministic and MUST NOT have side effects. The only inputs are the
    /// Rainlang string and the parse meta. MAY revert if the Rainlang string
    /// is invalid. This function takes `bytes` instead of `string` to allow
    /// for definitions of "string" other than UTF-8.
    /// @param data The Rainlang bytes to parse.
    /// @return bytecode The expressions that can be evaluated.
    /// @return constants The constants that can be referenced by sources.
    function parse(bytes calldata data) external pure returns (bytes calldata bytecode, uint256[] calldata constants);
}

File 51 of 55 : IInterpreterCallerV1.sol
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {IExpressionDeployerV1} from "./IExpressionDeployerV1.sol";
import {IExpressionDeployerV2} from "./IExpressionDeployerV2.sol";
import {IInterpreterV1} from "./IInterpreterV1.sol";
import {IInterpreterStoreV1} from "./IInterpreterStoreV1.sol";

/// Standard struct that can be embedded in ABIs in a consistent format for
/// tooling to read/write. MAY be useful to bundle up the data required to call
/// `IExpressionDeployerV1` but is NOT mandatory.
/// @param deployer Will deploy the expression from sources and constants.
/// @param sources Will be deployed to an expression address for use in
/// `Evaluable`.
/// @param constants Will be available to the expression at runtime.
struct EvaluableConfig {
    IExpressionDeployerV1 deployer;
    bytes[] sources;
    uint256[] constants;
}

/// Standard struct that can be embedded in ABIs in a consistent format for
/// tooling to read/write. MAY be useful to bundle up the data required to call
/// `IExpressionDeployerV2` but is NOT mandatory.
/// @param deployer Will deploy the expression from sources and constants.
/// @param bytecode Will be deployed to an expression address for use in
/// `Evaluable`.
/// @param constants Will be available to the expression at runtime.
struct EvaluableConfigV2 {
    IExpressionDeployerV2 deployer;
    bytes bytecode;
    uint256[] constants;
}

/// Struct over the return of `IExpressionDeployerV1.deployExpression`
/// which MAY be more convenient to work with than raw addresses.
/// @param interpreter Will evaluate the expression.
/// @param store Will store state changes due to evaluation of the expression.
/// @param expression Will be evaluated by the interpreter.
struct Evaluable {
    IInterpreterV1 interpreter;
    IInterpreterStoreV1 store;
    address expression;
}

/// Typed embodiment of some context data with associated signer and signature.
/// The signature MUST be over the packed encoded bytes of the context array,
/// i.e. the context array concatenated as bytes without the length prefix, then
/// hashed, then handled as per EIP-191 to produce a final hash to be signed.
///
/// The calling contract (likely with the help of `LibContext`) is responsible
/// for ensuring the authenticity of the signature, but not authorizing _who_ can
/// sign. IN ADDITION to authorisation of the signer to known-good entities the
/// expression is also responsible for:
///
/// - Enforcing the context is the expected data (e.g. with a domain separator)
/// - Tracking and enforcing nonces if signed contexts are only usable one time
/// - Tracking and enforcing uniqueness of signed data if relevant
/// - Checking and enforcing expiry times if present and relevant in the context
/// - Many other potential constraints that expressions may want to enforce
///
/// EIP-1271 smart contract signatures are supported in addition to EOA
/// signatures via. the Open Zeppelin `SignatureChecker` library, which is
/// wrapped by `LibContext.build`. As smart contract signatures are checked
/// onchain they CAN BE REVOKED AT ANY MOMENT as the smart contract can simply
/// return `false` when it previously returned `true`.
///
/// @param signer The account that produced the signature for `context`. The
/// calling contract MUST authenticate that the signer produced the signature.
/// @param signature The cryptographic signature for `context`. The calling
/// contract MUST authenticate that the signature is valid for the `signer` and
/// `context`.
/// @param context The signed data in a format that can be merged into a
/// 2-dimensional context matrix as-is.
struct SignedContext {
    // The ordering of these fields is important and used in assembly offset
    // calculations and hashing.
    address signer;
    bytes signature;
    uint256[] context;
}

uint256 constant SIGNED_CONTEXT_SIGNER_OFFSET = 0;
uint256 constant SIGNED_CONTEXT_CONTEXT_OFFSET = 0x20;
uint256 constant SIGNED_CONTEXT_SIGNATURE_OFFSET = 0x40;

/// @title IInterpreterCallerV1
/// @notice A contract that calls an `IInterpreterV1` via. `eval`. There are near
/// zero requirements on a caller other than:
///
/// - Emit some meta about itself upon construction so humans know what the
///   contract does
/// - Provide the context, which can be built in a standard way by `LibContext`
/// - Handle the stack array returned from `eval`
/// - OPTIONALLY emit the `Context` event
/// - OPTIONALLY set state on the `IInterpreterStoreV1` returned from eval.
interface IInterpreterCallerV1 {
    /// Calling contracts SHOULD emit `Context` before calling `eval` if they
    /// are able. Notably `eval` MAY be called within a static call which means
    /// that events cannot be emitted, in which case this does not apply. It MAY
    /// NOT be useful to emit this multiple times for several eval calls if they
    /// all share a common context, in which case a single emit is sufficient.
    /// @param sender `msg.sender` building the context.
    /// @param context The context that was built.
    event Context(address sender, uint256[][] context);
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {IInterpreterStoreV1} from "./IInterpreterStoreV1.sol";
import {IInterpreterV1} from "./IInterpreterV1.sol";

string constant IERC1820_NAME_IEXPRESSION_DEPLOYER_V2 = "IExpressionDeployerV2";

/// @title IExpressionDeployerV2
/// @notice Companion to `IInterpreterV1` responsible for onchain static code
/// analysis and deploying expressions. Each `IExpressionDeployerV2` is tightly
/// coupled at the bytecode level to some interpreter that it knows how to
/// analyse and deploy expressions for. The expression deployer can perform an
/// integrity check "dry run" of candidate source code for the intepreter. The
/// critical analysis/transformation includes:
///
/// - Enforcement of no out of bounds memory reads/writes
/// - Calculation of memory required to eval the stack with a single allocation
/// - Replacing index based opcodes with absolute interpreter function pointers
/// - Enforcement that all opcodes and operands used exist and are valid
///
/// This analysis is highly sensitive to the specific implementation and position
/// of all opcodes and function pointers as compiled into the interpreter. This
/// is what makes the coupling between an interpreter and expression deployer
/// so tight. Ideally all responsibilities would be handled by a single contract
/// but this introduces code size issues quickly by roughly doubling the compiled
/// logic of each opcode (half for the integrity check and half for evaluation).
///
/// Interpreters MUST assume that expression deployers are malicious and fail
/// gracefully if the integrity check is corrupt/bypassed and/or function
/// pointers are incorrect, etc. i.e. the interpreter MUST always return a stack
/// from `eval` in a read only way or error. I.e. it is the expression deployer's
/// responsibility to do everything it can to prevent undefined behaviour in the
/// interpreter, and the interpreter's responsibility to handle the expression
/// deployer completely failing to do so.
interface IExpressionDeployerV2 {
    /// This is the literal InterpreterOpMeta bytes to be used offchain to make
    /// sense of the opcodes in this interpreter deployment, as a human. For
    /// formats like json that make heavy use of boilerplate, repetition and
    /// whitespace, some kind of compression is recommended.
    /// @param sender The `msg.sender` providing the op meta.
    /// @param meta The raw binary data of the construction meta. Maybe
    /// compressed data etc. and is intended for offchain consumption.
    event DISpair(address sender, address deployer, address interpreter, address store, bytes meta);

    /// Expressions are expected to be deployed onchain as immutable contract
    /// code with a first class address like any other contract or account.
    /// Technically this is optional in the sense that all the tools required to
    /// eval some expression and define all its opcodes are available as
    /// libraries.
    ///
    /// In practise there are enough advantages to deploying the sources directly
    /// onchain as contract data and loading them from the interpreter at eval:
    ///
    /// - Loading and storing binary data is gas efficient as immutable contract
    ///   data
    /// - Expressions need to be immutable between their deploy time integrity
    ///   check and runtime evaluation
    /// - Passing the address of an expression through calldata to an interpreter
    ///   is cheaper than passing an entire expression through calldata
    /// - Conceptually a very simple approach, even if implementations like
    ///   SSTORE2 are subtle under the hood
    ///
    /// The expression deployer MUST perform an integrity check of the source
    /// code before it puts the expression onchain at a known address. The
    /// integrity check MUST at a minimum (it is free to do additional static
    /// analysis) calculate the memory required to be allocated for the stack in
    /// total, and that no out of bounds memory reads/writes occur within this
    /// stack. A simple example of an invalid source would be one that pushes one
    /// value to the stack then attempts to pops two values, clearly we cannot
    /// remove more values than we added. The `IExpressionDeployerV2` MUST revert
    /// in the case of any integrity failure, all integrity checks MUST pass in
    /// order for the deployment to complete.
    ///
    /// Once the integrity check is complete the `IExpressionDeployerV2` MUST do
    /// any additional processing required by its paired interpreter.
    /// For example, the `IExpressionDeployerV2` MAY NEED to replace the indexed
    /// opcodes in the `ExpressionConfig` sources with real function pointers
    /// from the corresponding interpreter.
    ///
    /// @param bytecode Bytecode verbatim. Exactly how the bytecode is structured
    /// is up to the deployer and interpreter. The deployer MUST NOT modify the
    /// bytecode in any way. The interpreter MUST NOT assume anything about the
    /// bytecode other than that it is valid according to the interpreter's
    /// integrity checks. It is assumed that the bytecode will be produced from
    /// a human friendly string via. `IParserV1.parse` but this is not required
    /// if the caller has some other means to prooduce valid bytecode.
    /// @param constants Constants verbatim. Constants are provided alongside
    /// sources rather than inline as it allows us to avoid variable length
    /// opcodes and can be more memory efficient if the same constant is
    /// referenced several times from the sources.
    /// @param minOutputs The first N sources on the state config are entrypoints
    /// to the expression where N is the length of the `minOutputs` array. Each
    /// item in the `minOutputs` array specifies the number of outputs that MUST
    /// be present on the final stack for an evaluation of each entrypoint. The
    /// minimum output for some entrypoint MAY be zero if the expectation is that
    /// the expression only applies checks and error logic. Non-entrypoint
    /// sources MUST NOT have a minimum outputs length specified.
    /// @return interpreter The interpreter the deployer believes it is qualified
    /// to perform integrity checks on behalf of.
    /// @return store The interpreter store the deployer believes is compatible
    /// with the interpreter.
    /// @return expression The address of the deployed onchain expression. MUST
    /// be valid according to all integrity checks the deployer is aware of.
    function deployExpression(bytes calldata bytecode, uint256[] calldata constants, uint256[] calldata minOutputs)
        external
        returns (IInterpreterV1 interpreter, IInterpreterStoreV1 store, address expression);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}

// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {IInterpreterStoreV1} from "./IInterpreterStoreV1.sol";
import {IInterpreterV1} from "./IInterpreterV1.sol";

string constant IERC1820_NAME_IEXPRESSION_DEPLOYER_V1 = "IExpressionDeployerV1";

/// @title IExpressionDeployerV1
/// @notice Companion to `IInterpreterV1` responsible for onchain static code
/// analysis and deploying expressions. Each `IExpressionDeployerV1` is tightly
/// coupled at the bytecode level to some interpreter that it knows how to
/// analyse and deploy expressions for. The expression deployer can perform an
/// integrity check "dry run" of candidate source code for the intepreter. The
/// critical analysis/transformation includes:
///
/// - Enforcement of no out of bounds memory reads/writes
/// - Calculation of memory required to eval the stack with a single allocation
/// - Replacing index based opcodes with absolute interpreter function pointers
/// - Enforcement that all opcodes and operands used exist and are valid
///
/// This analysis is highly sensitive to the specific implementation and position
/// of all opcodes and function pointers as compiled into the interpreter. This
/// is what makes the coupling between an interpreter and expression deployer
/// so tight. Ideally all responsibilities would be handled by a single contract
/// but this introduces code size issues quickly by roughly doubling the compiled
/// logic of each opcode (half for the integrity check and half for evaluation).
///
/// Interpreters MUST assume that expression deployers are malicious and fail
/// gracefully if the integrity check is corrupt/bypassed and/or function
/// pointers are incorrect, etc. i.e. the interpreter MUST always return a stack
/// from `eval` in a read only way or error. I.e. it is the expression deployer's
/// responsibility to do everything it can to prevent undefined behaviour in the
/// interpreter, and the interpreter's responsibility to handle the expression
/// deployer completely failing to do so.
interface IExpressionDeployerV1 {
    /// This is the literal InterpreterOpMeta bytes to be used offchain to make
    /// sense of the opcodes in this interpreter deployment, as a human. For
    /// formats like json that make heavy use of boilerplate, repetition and
    /// whitespace, some kind of compression is recommended.
    /// @param sender The `msg.sender` providing the op meta.
    /// @param opMeta The raw binary data of the op meta. Maybe compressed data
    /// etc. and is intended for offchain consumption.
    event DISpair(address sender, address deployer, address interpreter, address store, bytes opMeta);

    /// Expressions are expected to be deployed onchain as immutable contract
    /// code with a first class address like any other contract or account.
    /// Technically this is optional in the sense that all the tools required to
    /// eval some expression and define all its opcodes are available as
    /// libraries.
    ///
    /// In practise there are enough advantages to deploying the sources directly
    /// onchain as contract data and loading them from the interpreter at eval:
    ///
    /// - Loading and storing binary data is gas efficient as immutable contract
    ///   data
    /// - Expressions need to be immutable between their deploy time integrity
    ///   check and runtime evaluation
    /// - Passing the address of an expression through calldata to an interpreter
    ///   is cheaper than passing an entire expression through calldata
    /// - Conceptually a very simple approach, even if implementations like
    ///   SSTORE2 are subtle under the hood
    ///
    /// The expression deployer MUST perform an integrity check of the source
    /// code before it puts the expression onchain at a known address. The
    /// integrity check MUST at a minimum (it is free to do additional static
    /// analysis) calculate the memory required to be allocated for the stack in
    /// total, and that no out of bounds memory reads/writes occur within this
    /// stack. A simple example of an invalid source would be one that pushes one
    /// value to the stack then attempts to pops two values, clearly we cannot
    /// remove more values than we added. The `IExpressionDeployerV1` MUST revert
    /// in the case of any integrity failure, all integrity checks MUST pass in
    /// order for the deployment to complete.
    ///
    /// Once the integrity check is complete the `IExpressionDeployerV1` MUST do
    /// any additional processing required by its paired interpreter.
    /// For example, the `IExpressionDeployerV1` MAY NEED to replace the indexed
    /// opcodes in the `ExpressionConfig` sources with real function pointers
    /// from the corresponding interpreter.
    ///
    /// @param sources Sources verbatim. These sources MUST be provided in their
    /// sequential/index opcode form as the deployment process will need to index
    /// into BOTH the integrity check and the final runtime function pointers.
    /// This will be emitted in an event for offchain processing to use the
    /// indexed opcode sources. The first N sources are considered entrypoints
    /// and will be integrity checked by the expression deployer against a
    /// starting stack height of 0. Non-entrypoint sources MAY be provided for
    /// internal use such as the `call` opcode but will NOT be integrity checked
    /// UNLESS entered by an opcode in an entrypoint.
    /// @param constants Constants verbatim. Constants are provided alongside
    /// sources rather than inline as it allows us to avoid variable length
    /// opcodes and can be more memory efficient if the same constant is
    /// referenced several times from the sources.
    /// @param minOutputs The first N sources on the state config are entrypoints
    /// to the expression where N is the length of the `minOutputs` array. Each
    /// item in the `minOutputs` array specifies the number of outputs that MUST
    /// be present on the final stack for an evaluation of each entrypoint. The
    /// minimum output for some entrypoint MAY be zero if the expectation is that
    /// the expression only applies checks and error logic. Non-entrypoint
    /// sources MUST NOT have a minimum outputs length specified.
    /// @return interpreter The interpreter the deployer believes it is qualified
    /// to perform integrity checks on behalf of.
    /// @return store The interpreter store the deployer believes is compatible
    /// with the interpreter.
    /// @return expression The address of the deployed onchain expression. MUST
    /// be valid according to all integrity checks the deployer is aware of.
    function deployExpression(bytes[] memory sources, uint256[] memory constants, uint256[] memory minOutputs)
        external
        returns (IInterpreterV1 interpreter, IInterpreterStoreV1 store, address expression);
}

Settings
{
  "remappings": [
    "forge-std/=lib/rain.interpreter/lib/rain.interpreter.interface/lib/forge-std/src/",
    "openzeppelin-contracts/=lib/rain.orderbook.interface/lib/rain.interpreter.interface/lib/openzeppelin-contracts/",
    "rain.interpreter/=lib/rain.interpreter/src/",
    "rain.metadata/=lib/rain.interpreter/lib/rain.metadata/src/",
    "rain.interpreter.interface/=lib/rain.orderbook.interface/lib/rain.interpreter.interface/src/",
    "rain.intorastring/=lib/rain.interpreter/lib/rain.intorastring/",
    "rain.sol.codegen/=lib/rain.interpreter/lib/rain.sol.codegen/src/",
    "rain.solmem/=lib/rain.orderbook.interface/lib/rain.interpreter.interface/lib/rain.solmem/src/",
    "@prb/test/=lib/rain.interpreter/lib/prb-math/lib/prb-test/src/",
    "axelar-gmp-sdk-solidity/=lib/sushixswap-v2/lib/axelar-gmp-sdk-solidity/",
    "bytecode/=lib/rain.orderbook.interface/lib/rain.interpreter.interface/src/lib/bytecode/",
    "caller/=lib/rain.orderbook.interface/lib/rain.interpreter.interface/src/lib/caller/",
    "constants/=lib/rain.interpreter/src/lib/constants/",
    "deprecated/=lib/rain.orderbook.interface/lib/rain.interpreter.interface/src/lib/",
    "ds-test/=lib/sushixswap-v2/lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/rain.orderbook.interface/lib/rain.interpreter.interface/lib/openzeppelin-contracts/lib/erc4626-tests/",
    "eval/=lib/rain.interpreter/src/lib/eval/",
    "extern/=lib/rain.interpreter/src/lib/extern/",
    "forge-gas-snapshot/=lib/sushixswap-v2/lib/forge-gas-snapshot/src/",
    "integrity/=lib/rain.interpreter/src/lib/integrity/",
    "ns/=lib/rain.orderbook.interface/lib/rain.interpreter.interface/src/lib/ns/",
    "op/=lib/rain.interpreter/src/lib/op/",
    "openzeppelin/=lib/rain.orderbook.interface/lib/rain.interpreter.interface/lib/openzeppelin-contracts/contracts/",
    "parse/=lib/rain.interpreter/src/lib/parse/",
    "prb-math/=lib/rain.interpreter/lib/prb-math/src/",
    "prb-test/=lib/rain.interpreter/lib/prb-math/lib/prb-test/src/",
    "rain.chainlink/=lib/rain.interpreter/lib/rain.chainlink/src/",
    "rain.datacontract/=lib/rain.interpreter/lib/rain.math.float/lib/rain.datacontract/src/",
    "rain.lib.hash/=lib/rain.orderbook.interface/lib/rain.interpreter.interface/lib/rain.lib.hash/src/",
    "rain.lib.memkv/=lib/rain.interpreter/lib/rain.lib.memkv/src/",
    "rain.lib.typecast/=lib/rain.orderbook.interface/lib/rain.interpreter.interface/lib/rain.lib.typecast/src/",
    "rain.math.binary/=lib/rain.orderbook.interface/lib/rain.interpreter.interface/lib/rain.math.binary/src/",
    "rain.math.fixedpoint/=lib/rain.interpreter/lib/rain.math.fixedpoint/src/",
    "rain.math.float/=lib/rain.interpreter/lib/rain.math.float/",
    "rain.math.saturating/=lib/rain.interpreter/lib/rain.math.fixedpoint/lib/rain.math.saturating/src/",
    "rain.orderbook.interface/=lib/rain.orderbook.interface/src/",
    "sol.lib.binmaskflag/=lib/rain.interpreter/lib/sol.lib.binmaskflag/src/",
    "state/=lib/rain.interpreter/src/lib/state/",
    "sushixswap-v2/=lib/sushixswap-v2/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 1000000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": false
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"components":[{"internalType":"address","name":"orderBook","type":"address"},{"components":[{"components":[{"internalType":"contract IInterpreterV3","name":"interpreter","type":"address"},{"internalType":"contract IInterpreterStoreV2","name":"store","type":"address"},{"internalType":"bytes","name":"bytecode","type":"bytes"}],"internalType":"struct EvaluableV3","name":"evaluable","type":"tuple"},{"components":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"context","type":"uint256[]"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SignedContextV1[]","name":"signedContext","type":"tuple[]"}],"internalType":"struct TaskV1","name":"task","type":"tuple"},{"internalType":"bytes","name":"implementationData","type":"bytes"}],"internalType":"struct OrderBookV4ArbConfigV2","name":"config","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"}],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"NoOrders","type":"error"},{"inputs":[],"name":"WrongTask","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"components":[{"internalType":"address","name":"orderBook","type":"address"},{"components":[{"components":[{"internalType":"contract IInterpreterV3","name":"interpreter","type":"address"},{"internalType":"contract IInterpreterStoreV2","name":"store","type":"address"},{"internalType":"bytes","name":"bytecode","type":"bytes"}],"internalType":"struct EvaluableV3","name":"evaluable","type":"tuple"},{"components":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"context","type":"uint256[]"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SignedContextV1[]","name":"signedContext","type":"tuple[]"}],"internalType":"struct TaskV1","name":"task","type":"tuple"},{"internalType":"bytes","name":"implementationData","type":"bytes"}],"indexed":false,"internalType":"struct OrderBookV4ArbConfigV2","name":"config","type":"tuple"}],"name":"Construct","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[{"internalType":"contract IOrderBookV4","name":"orderBook","type":"address"},{"components":[{"internalType":"uint256","name":"minimumInput","type":"uint256"},{"internalType":"uint256","name":"maximumInput","type":"uint256"},{"internalType":"uint256","name":"maximumIORatio","type":"uint256"},{"components":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"components":[{"internalType":"contract IInterpreterV3","name":"interpreter","type":"address"},{"internalType":"contract IInterpreterStoreV2","name":"store","type":"address"},{"internalType":"bytes","name":"bytecode","type":"bytes"}],"internalType":"struct EvaluableV3","name":"evaluable","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"vaultId","type":"uint256"}],"internalType":"struct IO[]","name":"validInputs","type":"tuple[]"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"vaultId","type":"uint256"}],"internalType":"struct IO[]","name":"validOutputs","type":"tuple[]"},{"internalType":"bytes32","name":"nonce","type":"bytes32"}],"internalType":"struct OrderV3","name":"order","type":"tuple"},{"internalType":"uint256","name":"inputIOIndex","type":"uint256"},{"internalType":"uint256","name":"outputIOIndex","type":"uint256"},{"components":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"context","type":"uint256[]"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SignedContextV1[]","name":"signedContext","type":"tuple[]"}],"internalType":"struct TakeOrderConfigV3[]","name":"orders","type":"tuple[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct TakeOrdersConfigV3","name":"takeOrders","type":"tuple"},{"components":[{"components":[{"internalType":"contract IInterpreterV3","name":"interpreter","type":"address"},{"internalType":"contract IInterpreterStoreV2","name":"store","type":"address"},{"internalType":"bytes","name":"bytecode","type":"bytes"}],"internalType":"struct EvaluableV3","name":"evaluable","type":"tuple"},{"components":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"context","type":"uint256[]"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SignedContextV1[]","name":"signedContext","type":"tuple[]"}],"internalType":"struct TaskV1","name":"task","type":"tuple"}],"name":"arb3","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"iRouteProcessor","outputs":[{"internalType":"contract IRouteProcessor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"iTaskHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint256","name":"inputAmountSent","type":"uint256"},{"internalType":"uint256","name":"totalOutputAmount","type":"uint256"},{"internalType":"bytes","name":"takeOrdersData","type":"bytes"}],"name":"onTakeOrders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

60c0604052600060805234801561001557600080fd5b5060405161369d38038061369d83398101604081905261003491610396565b808060016000819055507f584f220334313e589a42a75ac60d4fa6ed5b02329a7255af822a0e4ac9cd5f1d338260405161006f92919061060f565b60405180910390a16020810151516040015151156100b65760208082015160405161009a920161066f565b60408051601f1981840301815291905280516020909101206080525b5050600081604001518060200190518101906100d29190610689565b6001600160a01b031660a052506106a69050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561011e5761011e6100e6565b60405290565b604080519081016001600160401b038111828210171561011e5761011e6100e6565b604051601f8201601f191681016001600160401b038111828210171561016e5761016e6100e6565b604052919050565b6001600160a01b038116811461018b57600080fd5b50565b60005b838110156101a9578181015183820152602001610191565b50506000910152565b600082601f8301126101c357600080fd5b81516001600160401b038111156101dc576101dc6100e6565b6101ef601f8201601f1916602001610146565b81815284602083860101111561020457600080fd5b61021582602083016020870161018e565b949350505050565b60006001600160401b03821115610236576102366100e6565b5060051b60200190565b600082601f83011261025157600080fd5b815160206102666102618361021d565b610146565b82815260059290921b8401810191818101908684111561028557600080fd5b8286015b8481101561038b5780516001600160401b03808211156102a857600080fd5b908801906060828b03601f190112156102c15760008081fd5b6102c96100fc565b868301516102d681610176565b8152604083810151838111156102ec5760008081fd5b8401603f81018d136102fe5760008081fd5b8881015161030e6102618261021d565b81815260059190911b82018301908a8101908f83111561032e5760008081fd5b928401925b8284101561034c5783518252928b0192908b0190610333565b858c01525050506060840151838111156103665760008081fd5b6103748d8a838801016101b2565b918301919091525085525050918301918301610289565b509695505050505050565b600060208083850312156103a957600080fd5b82516001600160401b03808211156103c057600080fd5b90840190606082870312156103d457600080fd5b6103dc6100fc565b82516103e781610176565b815282840151828111156103fa57600080fd5b83016040818903121561040c57600080fd5b610414610124565b81518481111561042357600080fd5b82016060818b03121561043557600080fd5b61043d6100fc565b815161044881610176565b81528188015161045781610176565b8189015260408201518681111561046d57600080fd5b6104798c8285016101b2565b604083015250825250818601518481111561049357600080fd5b61049f8a828501610240565b87830152508086840152505060408301519350818411156104bf57600080fd5b6104cb878585016101b2565b60408201529695505050505050565b600081518084526104f281602086016020860161018e565b601f01601f19169290920160200192915050565b6000604082516040855260018060a01b03808251166040870152602080830151606083821660608a015260408501519450606060808a015261054b60a08a01866104da565b888401518a82038b86015280518083529196508401925083860190600581901b870185016000805b838110156105fd57898303601f19018552865180518a168452888101518985018890528051888601819052908a0190849060808701905b808310156105ca5783518252928c019260019290920191908c01906105aa565b508e84015193508681038f8801526105e281856104da565b96505050505087870196508785019450600181019050610573565b50909c9b505050505050505050505050565b6001600160a01b0383811682526040602080840182905284519092169083015282015160608083015260009061064860a0840182610506565b90506040840151603f1984830301608085015261066582826104da565b9695505050505050565b6020815260006106826020830184610506565b9392505050565b60006020828403121561069b57600080fd5b815161068281610176565b60805160a051612fa96106f46000396000818160cf0152818161026c015281816102ae0152818161030701526103c901526000818161013b0152818161040c015261045d0152612fa96000f3fe60806040526004361061005a5760003560e01c80630f8cc55c116100435780630f8cc55c146100bd5780637ea0b76a1461011657806393be095e146101295761005a565b806301ffc9a714610068578063059bebe61461009d575b34801561006657600080fd5b005b34801561007457600080fd5b50610088610083366004611c93565b61016b565b60405190151581526020015b60405180910390f35b3480156100a957600080fd5b506100666100b8366004611cfa565b610250565b3480156100c957600080fd5b506100f17f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610094565b610066610124366004611da4565b6103f9565b34801561013557600080fd5b5061015d7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610094565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f059bebe60000000000000000000000000000000000000000000000000000000014806101fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f7ea0b76a00000000000000000000000000000000000000000000000000000000145b8061024a57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b61029273ffffffffffffffffffffffffffffffffffffffff87167f0000000000000000000000000000000000000000000000000000000000000000600061077f565b6102f373ffffffffffffffffffffffffffffffffffffffff87167f00000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61077f565b600061030182840184611f81565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632646478b89888a8930886040518763ffffffff1660e01b815260040161036896959493929190612024565b6020604051808303816000875af1158015610387573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ab919061207d565b90506103ef73ffffffffffffffffffffffffffffffffffffffff89167f0000000000000000000000000000000000000000000000000000000000000000600061077f565b5050505050505050565b610401610984565b61040a8161222f565b7f00000000000000000000000000000000000000000000000000000000000000001580159061047f575080604051602001610445919061232d565b604051602081830303815290604052805190602001207f000000000000000000000000000000000000000000000000000000000000000014155b156104b6576040517f8812562900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104c36060840184612438565b90506000036104fe576040517f9c95219f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061050d6060850185612438565b600081811061051e5761051e6124a0565b905060200281019061053091906124cf565b61053a908061250d565b610548906040810190612541565b6105556060870187612438565b6000818110610566576105666124a0565b905060200281019061057891906124cf565b6020013581811061058b5761058b6124a0565b6105a192602060609092020190810191506125a8565b905060006105b26060860186612438565b60008181106105c3576105c36124a0565b90506020028101906105d591906124cf565b6105df908061250d565b6105ed906060810190612541565b6105fa6060880188612438565b600081811061060b5761060b6124a0565b905060200281019061061d91906124cf565b60400135818110610630576106306124a0565b61064692602060609092020190810191506125a8565b905061066a73ffffffffffffffffffffffffffffffffffffffff831687600061077f565b6106ab73ffffffffffffffffffffffffffffffffffffffff8316877fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61077f565b6000808773ffffffffffffffffffffffffffffffffffffffff16630997c4a0886040518263ffffffff1660e01b81526004016106e7919061290c565b60408051808303816000875af1158015610705573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107299190612b8e565b909250905061075073ffffffffffffffffffffffffffffffffffffffff851689600061077f565b61076361075c8761222f565b85856109f7565b50505050506107726001600055565b505050565b505050505050565b80158061081f57506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa1580156107f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061081d919061207d565b155b6108b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526107729084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152610dcf565b6002600054036109f0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108a7565b6002600055565b604080516001808252818301909252600091816020015b6060815260200190600190039081610a0e575050604080516003808252608082019092529192506000919060208201606080368337019050506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa158015610ab7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610adb919061207d565b90508015610b0457610b0473ffffffffffffffffffffffffffffffffffffffff86163383610ede565b60008573ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b759190612bb2565b60ff169050610b8682826000610f34565b83600081518110610b9957610b996124a0565b602090810291909101015250506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa158015610c13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c37919061207d565b90508015610c6057610c6073ffffffffffffffffffffffffffffffffffffffff85163383610ede565b60008473ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd19190612bb2565b60ff169050610ce282826000610f34565b83600181518110610cf557610cf56124a0565b602090810291909101015250479050610d0e3382610fbc565b8082600281518110610d2257610d226124a0565b602002602001018181525050508082600081518110610d4357610d436124a0565b6020908102919091010152604080516001808252818301909252600091816020015b6040805160a08101825260009181018281526060808301939093526080820183905281526020810191909152815260200190600190039081610d655790505090508581600081518110610dba57610dba6124a0565b60200260200101819052506107778382611116565b6000610e31826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661132d9092919063ffffffff16565b9050805160001480610e52575080806020019051810190610e529190612bcf565b610772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016108a7565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526107729084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401610902565b60008260121115610f695760128390036002831615610f5f57610f578582611344565b915050610fb5565b610f5785826113d1565b6012831115610fb2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee83016001831615610fa857610f578582611409565b610f578582611457565b50825b9392505050565b80471015611026576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016108a7565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611080576040519150601f19603f3d011682016040523d82523d6000602084013e611085565b606091505b5050905080610772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016108a7565b336111496040805160a0810182526000918101828152606080830193909352608082018390528152602081019190915290565b60005b835181101561132657838181518110611167576111676124a0565b60200260200101519150600082600001516040015151111561131e578151805160209182015160008681523090935260408320839273ffffffffffffffffffffffffffffffffffffffff169163d6e3357a9187600001516040015160006111d28d8b6020015161147a565b604080516000815260208101918290527fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1690915261121e95949392919060248101612bf1565b600060405180830381865afa15801561123b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526112819190810190612d1e565b805191935091501561131b578351602001516040517f946aadc600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063946aadc6906112e89088908590600401612d82565b600060405180830381600087803b15801561130257600080fd5b505af1158015611316573d6000803e3d6000fd5b505050505b50505b60010161114c565b5050505050565b606061133c848460008561178a565b949350505050565b6000604e821061138457821561137a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61137d565b60005b905061024a565b50600a81900a828102908381838161139e5761139e612d9b565b04146113ca577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61133c565b5092915050565b600a81900a6113e08184612df9565b9050604e821061024a578215611400576113fb82600a612f30565b610fb5565b60009392505050565b6000604e821061142d578215611420576001611423565b60005b60ff16905061024a565b600a82900a80848161144157611441612d9b565b04915080820284146113ca575060010192915050565b6000604e8210156114005781600a0a838161147457611474612d9b565b04610fb5565b60606000825167ffffffffffffffff81111561149857611498611e29565b6040519080825280602002602001820160405280156114c1578160200160208202803683370190505b5090506000808451116114d55760006114db565b83516001015b855160010101905060008167ffffffffffffffff8111156114fe576114fe611e29565b60405190808252806020026020018201604052801561153157816020015b606081526020019060019003908161151c5790505b5090506000611556604080516002815233602082015230818301526060810190915290565b828281518110611568576115686124a0565b602002602001018190525060005b87518110156115c6578180600101925050878181518110611599576115996124a0565b60200260200101518383815181106115b3576115b36124a0565b6020908102919091010152600101611576565b50855115611780578080600101915050838282815181106115e9576115e96124a0565b602002602001018190525060005b865181101561177e576116a8878281518110611615576116156124a0565b6020026020010151600001516116856116528a8581518110611639576116396124a0565b6020026020010151602001518051602090810291012090565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000908152601c91909152603c902090565b898481518110611697576116976124a0565b6020026020010151604001516118a3565b6116e1576040517f52bf9848000000000000000000000000000000000000000000000000000000008152600481018290526024016108a7565b8681815181106116f3576116f36124a0565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff16858281518110611727576117276124a0565b602002602001018181525050818060010192505086818151811061174d5761174d6124a0565b60200260200101516020015183838151811061176b5761176b6124a0565b60209081029190910101526001016115f7565b505b5095945050505050565b60608247101561181c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016108a7565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516118459190612f3c565b60006040518083038185875af1925050503d8060008114611882576040519150601f19603f3d011682016040523d82523d6000602084013e611887565b606091505b50915091506118988783838761191e565b979650505050505050565b60008060006118b285856119be565b909250905060008160048111156118cb576118cb612f4e565b14801561190357508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119145750611914868686611a03565b9695505050505050565b606083156119b45782516000036119ad5773ffffffffffffffffffffffffffffffffffffffff85163b6119ad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108a7565b508161133c565b61133c8383611b60565b60008082516041036119f45760208301516040840151606085015160001a6119e887828585611ba4565b945094505050506119fc565b506000905060025b9250929050565b60008060008573ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b8686604051602401611a3a929190612f7d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611ac39190612f3c565b600060405180830381855afa9150503d8060008114611afe576040519150601f19603f3d011682016040523d82523d6000602084013e611b03565b606091505b5091509150818015611b1757506020815110155b8015611914575080517f1626ba7e0000000000000000000000000000000000000000000000000000000090611b55908301602090810190840161207d565b149695505050505050565b815115611b705781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108a79190612f96565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bdb5750600090506003611c8a565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c2f573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116611c8357600060019250925050611c8a565b9150600090505b94509492505050565b600060208284031215611ca557600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610fb557600080fd5b73ffffffffffffffffffffffffffffffffffffffff81168114611cf757600080fd5b50565b60008060008060008060a08789031215611d1357600080fd5b8635611d1e81611cd5565b95506020870135611d2e81611cd5565b94506040870135935060608701359250608087013567ffffffffffffffff80821115611d5957600080fd5b818901915089601f830112611d6d57600080fd5b813581811115611d7c57600080fd5b8a6020828501011115611d8e57600080fd5b6020830194508093505050509295509295509295565b600080600060608486031215611db957600080fd5b8335611dc481611cd5565b9250602084013567ffffffffffffffff80821115611de157600080fd5b9085019060a08288031215611df557600080fd5b90925060408501359080821115611e0b57600080fd5b50840160408187031215611e1e57600080fd5b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715611e7b57611e7b611e29565b60405290565b6040805190810167ffffffffffffffff81118282101715611e7b57611e7b611e29565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611eeb57611eeb611e29565b604052919050565b600082601f830112611f0457600080fd5b813567ffffffffffffffff811115611f1e57611f1e611e29565b611f4f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611ea4565b818152846020838601011115611f6457600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215611f9357600080fd5b813567ffffffffffffffff811115611faa57600080fd5b61133c84828501611ef3565b60005b83811015611fd1578181015183820152602001611fb9565b50506000910152565b60008151808452611ff2816020860160208601611fb6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600073ffffffffffffffffffffffffffffffffffffffff8089168352876020840152808716604084015285606084015280851660808401525060c060a083015261207160c0830184611fda565b98975050505050505050565b60006020828403121561208f57600080fd5b5051919050565b600067ffffffffffffffff8211156120b0576120b0611e29565b5060051b60200190565b600082601f8301126120cb57600080fd5b813560206120e06120db83612096565b611ea4565b82815260059290921b840181019181810190868411156120ff57600080fd5b8286015b8481101561222457803567ffffffffffffffff8082111561212357600080fd5b908801906060828b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001121561215a5760008081fd5b612162611e58565b8683013561216f81611cd5565b8152604083810135838111156121855760008081fd5b8401603f81018d136121975760008081fd5b888101356121a76120db82612096565b81815260059190911b82018301908a8101908f8311156121c75760008081fd5b928401925b828410156121e55783358252928b0192908b01906121cc565b858c01525050506060840135838111156121ff5760008081fd5b61220d8d8a83880101611ef3565b918301919091525085525050918301918301612103565b509695505050505050565b60006040823603121561224157600080fd5b612249611e81565b823567ffffffffffffffff8082111561226157600080fd5b81850191506060823603121561227657600080fd5b61227e611e58565b823561228981611cd5565b8152602083013561229981611cd5565b60208201526040830135828111156122b057600080fd5b6122bc36828601611ef3565b604083015250835260208501359150808211156122d857600080fd5b506122e5368286016120ba565b60208301525092915050565b60008151808452602080850194506020840160005b8381101561232257815187529582019590820190600101612306565b509495945050505050565b60006020808352606084516040808487015273ffffffffffffffffffffffffffffffffffffffff808351166060880152808584015116608088015260408301519250606060a088015261238360c0880184611fda565b9250848801517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808986030160408a01528482518087528887019150888160051b880101898501945060005b82811015612427578489830301845285518781511683528b8101518b8d8501526123fb8c8501826122f1565b918a0151848303858c01529190506124138183611fda565b978d0197958d0195935050506001016123cf565b509c9b505050505050505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261246d57600080fd5b83018035915067ffffffffffffffff82111561248857600080fd5b6020019150600581901b36038213156119fc57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261250357600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261250357600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261257657600080fd5b83018035915067ffffffffffffffff82111561259157600080fd5b60200191506060810236038213156119fc57600080fd5b6000602082840312156125ba57600080fd5b8135610fb581611cd5565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126125fa57600080fd5b830160208101925035905067ffffffffffffffff81111561261a57600080fd5b8060051b36038213156119fc57600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261266057600080fd5b90910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261269e57600080fd5b830160208101925035905067ffffffffffffffff8111156126be57600080fd5b8036038213156119fc57600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261274b57600080fd5b830160208101925035905067ffffffffffffffff81111561276b57600080fd5b6060810236038213156119fc57600080fd5b60ff81168114611cf757600080fd5b8183526000602080850194508260005b858110156123225781356127af81611cd5565b73ffffffffffffffffffffffffffffffffffffffff168752818301356127d48161277d565b60ff1687840152604082810135908801526060968701969091019060010161279c565b818352602080840193600091600585811b830182018585805b898110156128fd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0878503018b52612849838a61262c565b6060813561285681611cd5565b73ffffffffffffffffffffffffffffffffffffffff16865261287a828901836125c5565b828a8901528083890152608092507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156128b4578586fd5b881b8082898501378701905060406128ce84820185612669565b94508389840301828a01526128e684840186836126cd565b9f8b019f9850505094880194505050600101612810565b50919998505050505050505050565b6000602080835260c08301843582850152604082860135818601526060818701358187015261293d818801886125c5565b60a060808901528481865260e08901905060e08260051b8a010195508260005b83811015612b43577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff208b890301835281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818636030181126129be57600080fd5b85018035368290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610181126129f357600080fd5b60808a5281018035612a0481611cd5565b73ffffffffffffffffffffffffffffffffffffffff80821660808d0152612a2d8d84018461262c565b915060a0808d01528135612a4081611cd5565b81166101208d0152818d0135612a5581611cd5565b166101408c0152612a68818b0182612669565b9150896101608d0152612a806101808d0183836126cd565b915050612a8f8a830183612716565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80808e85030160c08f0152612ac584838561278c565b9350612ad38c860186612716565b93509150808e85030160e08f015250612aed83838361278c565b9250505060808201356101008c01528b8301358c8c0152898301358a8c0152612b18898401846125c5565b935091508a8103898c0152612b2e8184846127f7565b9a50505092890192509088019060010161295d565b50505050505050612b576080860186612669565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08583030160a08601526119148284836126cd565b60008060408385031215612ba157600080fd5b505080516020909101519092909150565b600060208284031215612bc457600080fd5b8151610fb58161277d565b600060208284031215612be157600080fd5b81518015158114610fb557600080fd5b73ffffffffffffffffffffffffffffffffffffffff8716815260006020878184015260c06040840152612c2760c0840188611fda565b86606085015283810360808501528086518083528383019150838160051b84010184890160005b83811015612c9a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018552612c888383516122f1565b94870194925090860190600101612c4e565b505086810360a0880152612cae81896122f1565b9d9c50505050505050505050505050565b600082601f830112612cd057600080fd5b81516020612ce06120db83612096565b8083825260208201915060208460051b870101935086841115612d0257600080fd5b602086015b848110156122245780518352918301918301612d07565b60008060408385031215612d3157600080fd5b825167ffffffffffffffff80821115612d4957600080fd5b612d5586838701612cbf565b93506020850151915080821115612d6b57600080fd5b50612d7885828601612cbf565b9150509250929050565b82815260406020820152600061133c60408301846122f1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761024a5761024a612dca565b600181815b80851115612e6957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115612e4f57612e4f612dca565b80851615612e5c57918102915b93841c9390800290612e15565b509250929050565b600082612e805750600161024a565b81612e8d5750600061024a565b8160018114612ea35760028114612ead57612ec9565b600191505061024a565b60ff841115612ebe57612ebe612dca565b50506001821b61024a565b5060208310610133831016604e8410600b8410161715612eec575081810a61024a565b612ef68383612e10565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115612f2857612f28612dca565b029392505050565b6000610fb58383612e71565b60008251612503818460208701611fb6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b82815260406020820152600061133c6040830184611fda565b602081526000610fb56020830184611fda560000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000544ba588efd839d2692fc31ea991cd39993c135f

Deployed Bytecode

0x60806040526004361061005a5760003560e01c80630f8cc55c116100435780630f8cc55c146100bd5780637ea0b76a1461011657806393be095e146101295761005a565b806301ffc9a714610068578063059bebe61461009d575b34801561006657600080fd5b005b34801561007457600080fd5b50610088610083366004611c93565b61016b565b60405190151581526020015b60405180910390f35b3480156100a957600080fd5b506100666100b8366004611cfa565b610250565b3480156100c957600080fd5b506100f17f000000000000000000000000544ba588efd839d2692fc31ea991cd39993c135f81565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610094565b610066610124366004611da4565b6103f9565b34801561013557600080fd5b5061015d7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610094565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f059bebe60000000000000000000000000000000000000000000000000000000014806101fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f7ea0b76a00000000000000000000000000000000000000000000000000000000145b8061024a57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b61029273ffffffffffffffffffffffffffffffffffffffff87167f000000000000000000000000544ba588efd839d2692fc31ea991cd39993c135f600061077f565b6102f373ffffffffffffffffffffffffffffffffffffffff87167f000000000000000000000000544ba588efd839d2692fc31ea991cd39993c135f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61077f565b600061030182840184611f81565b905060007f000000000000000000000000544ba588efd839d2692fc31ea991cd39993c135f73ffffffffffffffffffffffffffffffffffffffff16632646478b89888a8930886040518763ffffffff1660e01b815260040161036896959493929190612024565b6020604051808303816000875af1158015610387573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ab919061207d565b90506103ef73ffffffffffffffffffffffffffffffffffffffff89167f000000000000000000000000544ba588efd839d2692fc31ea991cd39993c135f600061077f565b5050505050505050565b610401610984565b61040a8161222f565b7f00000000000000000000000000000000000000000000000000000000000000001580159061047f575080604051602001610445919061232d565b604051602081830303815290604052805190602001207f000000000000000000000000000000000000000000000000000000000000000014155b156104b6576040517f8812562900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104c36060840184612438565b90506000036104fe576040517f9c95219f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061050d6060850185612438565b600081811061051e5761051e6124a0565b905060200281019061053091906124cf565b61053a908061250d565b610548906040810190612541565b6105556060870187612438565b6000818110610566576105666124a0565b905060200281019061057891906124cf565b6020013581811061058b5761058b6124a0565b6105a192602060609092020190810191506125a8565b905060006105b26060860186612438565b60008181106105c3576105c36124a0565b90506020028101906105d591906124cf565b6105df908061250d565b6105ed906060810190612541565b6105fa6060880188612438565b600081811061060b5761060b6124a0565b905060200281019061061d91906124cf565b60400135818110610630576106306124a0565b61064692602060609092020190810191506125a8565b905061066a73ffffffffffffffffffffffffffffffffffffffff831687600061077f565b6106ab73ffffffffffffffffffffffffffffffffffffffff8316877fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61077f565b6000808773ffffffffffffffffffffffffffffffffffffffff16630997c4a0886040518263ffffffff1660e01b81526004016106e7919061290c565b60408051808303816000875af1158015610705573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107299190612b8e565b909250905061075073ffffffffffffffffffffffffffffffffffffffff851689600061077f565b61076361075c8761222f565b85856109f7565b50505050506107726001600055565b505050565b505050505050565b80158061081f57506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa1580156107f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061081d919061207d565b155b6108b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526107729084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152610dcf565b6002600054036109f0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108a7565b6002600055565b604080516001808252818301909252600091816020015b6060815260200190600190039081610a0e575050604080516003808252608082019092529192506000919060208201606080368337019050506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa158015610ab7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610adb919061207d565b90508015610b0457610b0473ffffffffffffffffffffffffffffffffffffffff86163383610ede565b60008573ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b759190612bb2565b60ff169050610b8682826000610f34565b83600081518110610b9957610b996124a0565b602090810291909101015250506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa158015610c13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c37919061207d565b90508015610c6057610c6073ffffffffffffffffffffffffffffffffffffffff85163383610ede565b60008473ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd19190612bb2565b60ff169050610ce282826000610f34565b83600181518110610cf557610cf56124a0565b602090810291909101015250479050610d0e3382610fbc565b8082600281518110610d2257610d226124a0565b602002602001018181525050508082600081518110610d4357610d436124a0565b6020908102919091010152604080516001808252818301909252600091816020015b6040805160a08101825260009181018281526060808301939093526080820183905281526020810191909152815260200190600190039081610d655790505090508581600081518110610dba57610dba6124a0565b60200260200101819052506107778382611116565b6000610e31826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661132d9092919063ffffffff16565b9050805160001480610e52575080806020019051810190610e529190612bcf565b610772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016108a7565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526107729084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401610902565b60008260121115610f695760128390036002831615610f5f57610f578582611344565b915050610fb5565b610f5785826113d1565b6012831115610fb2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee83016001831615610fa857610f578582611409565b610f578582611457565b50825b9392505050565b80471015611026576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016108a7565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611080576040519150601f19603f3d011682016040523d82523d6000602084013e611085565b606091505b5050905080610772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016108a7565b336111496040805160a0810182526000918101828152606080830193909352608082018390528152602081019190915290565b60005b835181101561132657838181518110611167576111676124a0565b60200260200101519150600082600001516040015151111561131e578151805160209182015160008681523090935260408320839273ffffffffffffffffffffffffffffffffffffffff169163d6e3357a9187600001516040015160006111d28d8b6020015161147a565b604080516000815260208101918290527fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1690915261121e95949392919060248101612bf1565b600060405180830381865afa15801561123b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526112819190810190612d1e565b805191935091501561131b578351602001516040517f946aadc600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063946aadc6906112e89088908590600401612d82565b600060405180830381600087803b15801561130257600080fd5b505af1158015611316573d6000803e3d6000fd5b505050505b50505b60010161114c565b5050505050565b606061133c848460008561178a565b949350505050565b6000604e821061138457821561137a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61137d565b60005b905061024a565b50600a81900a828102908381838161139e5761139e612d9b565b04146113ca577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61133c565b5092915050565b600a81900a6113e08184612df9565b9050604e821061024a578215611400576113fb82600a612f30565b610fb5565b60009392505050565b6000604e821061142d578215611420576001611423565b60005b60ff16905061024a565b600a82900a80848161144157611441612d9b565b04915080820284146113ca575060010192915050565b6000604e8210156114005781600a0a838161147457611474612d9b565b04610fb5565b60606000825167ffffffffffffffff81111561149857611498611e29565b6040519080825280602002602001820160405280156114c1578160200160208202803683370190505b5090506000808451116114d55760006114db565b83516001015b855160010101905060008167ffffffffffffffff8111156114fe576114fe611e29565b60405190808252806020026020018201604052801561153157816020015b606081526020019060019003908161151c5790505b5090506000611556604080516002815233602082015230818301526060810190915290565b828281518110611568576115686124a0565b602002602001018190525060005b87518110156115c6578180600101925050878181518110611599576115996124a0565b60200260200101518383815181106115b3576115b36124a0565b6020908102919091010152600101611576565b50855115611780578080600101915050838282815181106115e9576115e96124a0565b602002602001018190525060005b865181101561177e576116a8878281518110611615576116156124a0565b6020026020010151600001516116856116528a8581518110611639576116396124a0565b6020026020010151602001518051602090810291012090565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000908152601c91909152603c902090565b898481518110611697576116976124a0565b6020026020010151604001516118a3565b6116e1576040517f52bf9848000000000000000000000000000000000000000000000000000000008152600481018290526024016108a7565b8681815181106116f3576116f36124a0565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff16858281518110611727576117276124a0565b602002602001018181525050818060010192505086818151811061174d5761174d6124a0565b60200260200101516020015183838151811061176b5761176b6124a0565b60209081029190910101526001016115f7565b505b5095945050505050565b60608247101561181c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016108a7565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516118459190612f3c565b60006040518083038185875af1925050503d8060008114611882576040519150601f19603f3d011682016040523d82523d6000602084013e611887565b606091505b50915091506118988783838761191e565b979650505050505050565b60008060006118b285856119be565b909250905060008160048111156118cb576118cb612f4e565b14801561190357508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b806119145750611914868686611a03565b9695505050505050565b606083156119b45782516000036119ad5773ffffffffffffffffffffffffffffffffffffffff85163b6119ad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108a7565b508161133c565b61133c8383611b60565b60008082516041036119f45760208301516040840151606085015160001a6119e887828585611ba4565b945094505050506119fc565b506000905060025b9250929050565b60008060008573ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b8686604051602401611a3a929190612f7d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611ac39190612f3c565b600060405180830381855afa9150503d8060008114611afe576040519150601f19603f3d011682016040523d82523d6000602084013e611b03565b606091505b5091509150818015611b1757506020815110155b8015611914575080517f1626ba7e0000000000000000000000000000000000000000000000000000000090611b55908301602090810190840161207d565b149695505050505050565b815115611b705781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108a79190612f96565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611bdb5750600090506003611c8a565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611c2f573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116611c8357600060019250925050611c8a565b9150600090505b94509492505050565b600060208284031215611ca557600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610fb557600080fd5b73ffffffffffffffffffffffffffffffffffffffff81168114611cf757600080fd5b50565b60008060008060008060a08789031215611d1357600080fd5b8635611d1e81611cd5565b95506020870135611d2e81611cd5565b94506040870135935060608701359250608087013567ffffffffffffffff80821115611d5957600080fd5b818901915089601f830112611d6d57600080fd5b813581811115611d7c57600080fd5b8a6020828501011115611d8e57600080fd5b6020830194508093505050509295509295509295565b600080600060608486031215611db957600080fd5b8335611dc481611cd5565b9250602084013567ffffffffffffffff80821115611de157600080fd5b9085019060a08288031215611df557600080fd5b90925060408501359080821115611e0b57600080fd5b50840160408187031215611e1e57600080fd5b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715611e7b57611e7b611e29565b60405290565b6040805190810167ffffffffffffffff81118282101715611e7b57611e7b611e29565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611eeb57611eeb611e29565b604052919050565b600082601f830112611f0457600080fd5b813567ffffffffffffffff811115611f1e57611f1e611e29565b611f4f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611ea4565b818152846020838601011115611f6457600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215611f9357600080fd5b813567ffffffffffffffff811115611faa57600080fd5b61133c84828501611ef3565b60005b83811015611fd1578181015183820152602001611fb9565b50506000910152565b60008151808452611ff2816020860160208601611fb6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600073ffffffffffffffffffffffffffffffffffffffff8089168352876020840152808716604084015285606084015280851660808401525060c060a083015261207160c0830184611fda565b98975050505050505050565b60006020828403121561208f57600080fd5b5051919050565b600067ffffffffffffffff8211156120b0576120b0611e29565b5060051b60200190565b600082601f8301126120cb57600080fd5b813560206120e06120db83612096565b611ea4565b82815260059290921b840181019181810190868411156120ff57600080fd5b8286015b8481101561222457803567ffffffffffffffff8082111561212357600080fd5b908801906060828b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001121561215a5760008081fd5b612162611e58565b8683013561216f81611cd5565b8152604083810135838111156121855760008081fd5b8401603f81018d136121975760008081fd5b888101356121a76120db82612096565b81815260059190911b82018301908a8101908f8311156121c75760008081fd5b928401925b828410156121e55783358252928b0192908b01906121cc565b858c01525050506060840135838111156121ff5760008081fd5b61220d8d8a83880101611ef3565b918301919091525085525050918301918301612103565b509695505050505050565b60006040823603121561224157600080fd5b612249611e81565b823567ffffffffffffffff8082111561226157600080fd5b81850191506060823603121561227657600080fd5b61227e611e58565b823561228981611cd5565b8152602083013561229981611cd5565b60208201526040830135828111156122b057600080fd5b6122bc36828601611ef3565b604083015250835260208501359150808211156122d857600080fd5b506122e5368286016120ba565b60208301525092915050565b60008151808452602080850194506020840160005b8381101561232257815187529582019590820190600101612306565b509495945050505050565b60006020808352606084516040808487015273ffffffffffffffffffffffffffffffffffffffff808351166060880152808584015116608088015260408301519250606060a088015261238360c0880184611fda565b9250848801517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808986030160408a01528482518087528887019150888160051b880101898501945060005b82811015612427578489830301845285518781511683528b8101518b8d8501526123fb8c8501826122f1565b918a0151848303858c01529190506124138183611fda565b978d0197958d0195935050506001016123cf565b509c9b505050505050505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261246d57600080fd5b83018035915067ffffffffffffffff82111561248857600080fd5b6020019150600581901b36038213156119fc57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261250357600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261250357600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261257657600080fd5b83018035915067ffffffffffffffff82111561259157600080fd5b60200191506060810236038213156119fc57600080fd5b6000602082840312156125ba57600080fd5b8135610fb581611cd5565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126125fa57600080fd5b830160208101925035905067ffffffffffffffff81111561261a57600080fd5b8060051b36038213156119fc57600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261266057600080fd5b90910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261269e57600080fd5b830160208101925035905067ffffffffffffffff8111156126be57600080fd5b8036038213156119fc57600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261274b57600080fd5b830160208101925035905067ffffffffffffffff81111561276b57600080fd5b6060810236038213156119fc57600080fd5b60ff81168114611cf757600080fd5b8183526000602080850194508260005b858110156123225781356127af81611cd5565b73ffffffffffffffffffffffffffffffffffffffff168752818301356127d48161277d565b60ff1687840152604082810135908801526060968701969091019060010161279c565b818352602080840193600091600585811b830182018585805b898110156128fd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0878503018b52612849838a61262c565b6060813561285681611cd5565b73ffffffffffffffffffffffffffffffffffffffff16865261287a828901836125c5565b828a8901528083890152608092507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156128b4578586fd5b881b8082898501378701905060406128ce84820185612669565b94508389840301828a01526128e684840186836126cd565b9f8b019f9850505094880194505050600101612810565b50919998505050505050505050565b6000602080835260c08301843582850152604082860135818601526060818701358187015261293d818801886125c5565b60a060808901528481865260e08901905060e08260051b8a010195508260005b83811015612b43577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff208b890301835281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818636030181126129be57600080fd5b85018035368290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610181126129f357600080fd5b60808a5281018035612a0481611cd5565b73ffffffffffffffffffffffffffffffffffffffff80821660808d0152612a2d8d84018461262c565b915060a0808d01528135612a4081611cd5565b81166101208d0152818d0135612a5581611cd5565b166101408c0152612a68818b0182612669565b9150896101608d0152612a806101808d0183836126cd565b915050612a8f8a830183612716565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80808e85030160c08f0152612ac584838561278c565b9350612ad38c860186612716565b93509150808e85030160e08f015250612aed83838361278c565b9250505060808201356101008c01528b8301358c8c0152898301358a8c0152612b18898401846125c5565b935091508a8103898c0152612b2e8184846127f7565b9a50505092890192509088019060010161295d565b50505050505050612b576080860186612669565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08583030160a08601526119148284836126cd565b60008060408385031215612ba157600080fd5b505080516020909101519092909150565b600060208284031215612bc457600080fd5b8151610fb58161277d565b600060208284031215612be157600080fd5b81518015158114610fb557600080fd5b73ffffffffffffffffffffffffffffffffffffffff8716815260006020878184015260c06040840152612c2760c0840188611fda565b86606085015283810360808501528086518083528383019150838160051b84010184890160005b83811015612c9a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018552612c888383516122f1565b94870194925090860190600101612c4e565b505086810360a0880152612cae81896122f1565b9d9c50505050505050505050505050565b600082601f830112612cd057600080fd5b81516020612ce06120db83612096565b8083825260208201915060208460051b870101935086841115612d0257600080fd5b602086015b848110156122245780518352918301918301612d07565b60008060408385031215612d3157600080fd5b825167ffffffffffffffff80821115612d4957600080fd5b612d5586838701612cbf565b93506020850151915080821115612d6b57600080fd5b50612d7885828601612cbf565b9150509250929050565b82815260406020820152600061133c60408301846122f1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761024a5761024a612dca565b600181815b80851115612e6957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115612e4f57612e4f612dca565b80851615612e5c57918102915b93841c9390800290612e15565b509250929050565b600082612e805750600161024a565b81612e8d5750600061024a565b8160018114612ea35760028114612ead57612ec9565b600191505061024a565b60ff841115612ebe57612ebe612dca565b50506001821b61024a565b5060208310610133831016604e8410600b8410161715612eec575081810a61024a565b612ef68383612e10565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115612f2857612f28612dca565b029392505050565b6000610fb58383612e71565b60008251612503818460208701611fb6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b82815260406020820152600061133c6040830184611fda565b602081526000610fb56020830184611fda56

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000544ba588efd839d2692fc31ea991cd39993c135f

-----Decoded View---------------
Arg [0] : config (tuple):
Arg [1] : orderBook (address): 0x0000000000000000000000000000000000000000
Arg [2] : task (tuple):
Arg [1] : evaluable (tuple):
Arg [1] : interpreter (address): 0x0000000000000000000000000000000000000000
Arg [2] : store (address): 0x0000000000000000000000000000000000000000
Arg [3] : bytecode (bytes): 0x


Arg [3] : implementationData (bytes): 0x000000000000000000000000544ba588efd839d2692fc31ea991cd39993c135f


-----Encoded View---------------
13 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [5] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [12] : 000000000000000000000000544ba588efd839d2692fc31ea991cd39993c135f


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.