{"file_path":"src/Gateway.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: LGPL-3.0-or-later\npragma solidity 0.8.35;\n//   /$$$$$$  /$$$$$$$   /$$$$$$   /$$$$$$  /$$$$$$$  /$$$$$$$$\n//  /$$__  $$| $$__  $$ /$$__  $$ /$$__  $$| $$__  $$| $$_____/\n// | $$  \\ $$| $$  \\ $$| $$  \\__/| $$  \\ $$| $$  \\ $$| $$\n// | $$  | $$| $$$$$$$/| $$      | $$  | $$| $$  | $$| $$$$$\n// | $$  | $$| $$____/ | $$      | $$  | $$| $$  | $$| $$__/\n// | $$  | $$| $$      | $$    $$| $$  | $$| $$  | $$| $$\n// |  $$$$$$/| $$      |  $$$$$$/|  $$$$$$/| $$$$$$$/| $$$$$$$$\n//  \\______/ |__/       \\______/  \\______/ |_______/ |________/\n//\n//\n//\n\nimport {Executor} from \"./Executor.sol\";\nimport {InteractionModule} from \"./InteractionModule.sol\";\nimport {SolverList} from \"./SolverList.sol\";\nimport {Module} from \"./libraries/Module.sol\";\nimport {OrderLib} from \"./libraries/Order.sol\";\nimport {SafeERC20} from \"./libraries/SafeERC20.sol\";\n\n/// @dev EIP-1271 contract-signature interface; returns `0x1626ba7e` when valid.\ninterface IERC1271 {\n    function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4 magicValue);\n}\n\n/// @dev Minimal ERC20 balance view — only `balanceOf` is read, to size a\n/// stray-fund recovery sweep of THIS Gateway's OWN balance.\ninterface IERC20 {\n    function balanceOf(address account) external view returns (uint256);\n}\n\n/// @title Opcode Gateway (solver entry + auth/custody core)\n/// @notice Batch settlement without uniform clearing prices and without buy\n/// orders: solvers submit per-trade executed amounts, each fenced by a\n/// cross-multiplication limit against the signed sell/buy amounts. This is the\n/// contract users approve and the allow-listed solver entry; it holds all auth\n/// state (pre-signatures, fills, EIP-712 domain), the reentrancy lock, and the\n/// solver allow-list. It NEVER delegatecalls.\n///\n/// PRIME DIRECTIVE — users can never be drained; only the Executor's buffers may\n/// be at risk. Held by: (1) the ONLY mover of a USER's funds is the locked,\n/// verified `_pull` — a private `transferFrom` straight from the signed order's\n/// owner into the Executor; (2) the lock lives in THIS contract's storage (a\n/// module-as-Executor cannot clear it cross-account); (3) the triple wall\n/// (notExecutor/onlySolver/lock) blocks a module re-entering settle; (4) phase\n/// delegates run AS the Executor, buffer-confined, on amounts/recipients captured\n/// in `Verified[]` memory before any module runs — a `top` phase (before pull)\n/// cannot change the pull and a `bot` phase (after pay) cannot claw back what was\n/// paid. Removing a guard requires first refuting this argument.\n///\n/// STRAY-FUND RECOVERY DOES NOT WEAKEN THIS. The `recover*` family added below\n/// moves funds with `transfer` (never `transferFrom`) and takes NO `from`/source\n/// parameter — it sweeps ONLY this Gateway's OWN balance. That balance is NEVER\n/// user funds: the protocol never credits the Gateway (the sole user-fund\n/// movement, `_pull`, lands the sell in the EXECUTOR), so anything resting on the\n/// Gateway is accidental / force-fed. A user's standing `type(uint256).max` approval to this\n/// Gateway is therefore untouchable by `recover*` — there is no code path that\n/// turns an approval into a pull outside `_pull`. The `recover*` entries reuse the\n/// exact `notExecutor onlySolver nonReentrant` gate as `settle*`.\ncontract Gateway {\n    // ---------------------------------------------------------------- errors\n\n    /// @dev Caller of settle is not an allow-listed solver.\n    error NotSolver();\n    /// @dev The Executor attempted to call settle — wall 1, a hardcoded guard\n    /// independent of SolverList state (holds even if a manager mis-adds the\n    /// Executor), blocking a module-as-Executor from re-entering settle.\n    error ForbiddenSolver();\n    /// @dev Reentrant call into settle (lock already held).\n    error Reentrancy();\n    /// @dev The order's `validTo` lies in the past.\n    error OrderExpired();\n    /// @dev Zero order `sellAmount`/`buyAmount` or zero `executedSellAmount` —\n    /// the zero-amount drain killer (such fills are unfillable / unreplayable).\n    error ZeroAmount();\n    /// @dev Signature bytes too short for the declared scheme.\n    error MalformedSignature();\n    /// @dev Unknown signature scheme byte.\n    error UnknownSignatureScheme();\n    /// @dev Scheme-3 order with no on-chain pre-signature for this digest.\n    error NotPreSigned();\n    /// @dev Attempt to pre-sign for the Gateway or Executor (neither may ever be\n    /// an order owner). See `setPreSignature`.\n    error SelfPreSignForbidden();\n    /// @dev ECDSA recovery returned the zero address.\n    error InvalidSignature();\n    /// @dev The EIP-1271 owner contract did not return the magic value.\n    error InvalidEip1271Signature();\n    /// @dev Fill-or-kill order already filled or invalidated.\n    error OrderAlreadyFilled();\n    /// @dev Fill-or-kill order executed with an amount != its full `sellAmount`.\n    error FillOrKillMismatch();\n    /// @dev Partial fill exceeds the remaining fillable amount (or order\n    /// invalidated / fully filled).\n    error OrderOverfill();\n    /// @dev The trade's executed amounts violate the order's signed limit.\n    error LimitNotMet();\n    /// @dev A stray-fund recovery found a zero balance — nothing to sweep, so\n    /// the call reverts rather than emit a no-op event / 0-value transfer.\n    error NothingToRecover();\n    /// @dev `recoverEth`'s native transfer to the recipient failed.\n    error EthRecoveryFailed();\n\n    // ---------------------------------------------------------------- events\n\n    /// @dev One event per executed trade — the only per-trade settlement log. Now\n    /// carries the FULL execution: the owner + both token legs (all indexed for\n    /// filtering), the resolved receiver, the order digest, and the executed\n    /// amounts — so an indexer needs nothing else to describe the swap.\n    event Trade(\n        address indexed owner,\n        address indexed sellToken,\n        address indexed buyToken,\n        address receiver,\n        bytes32 orderDigest,\n        uint256 executedSellAmount,\n        uint256 executedBuyAmount\n    );\n\n    /// @dev An order digest was invalidated for `owner`.\n    event OrderInvalidated(address indexed owner, bytes32 orderDigest);\n\n    /// @dev `owner` set or cleared an on-chain pre-signature for `orderDigest`.\n    event PreSignatureSet(address indexed owner, bytes32 orderDigest, bool signed);\n\n    /// @dev Stray ERC20 `token` swept off the Gateway to `to`. Solver-gated;\n    /// moves only this Gateway's OWN balance, which is never user funds.\n    event Recovered(address indexed token, address indexed to, uint256 amount);\n    /// @dev Stray native ETH swept off the Gateway to `to`.\n    event EthRecovered(address indexed to, uint256 amount);\n\n    // -------------------------------------------------------------- EIP-712\n\n    /// @dev EIP-712 domain name — a protocol constant.\n    string public constant DOMAIN_NAME = \"Opcode\";\n\n    /// @dev EIP-712 domain version — a protocol constant.\n    string public constant DOMAIN_VERSION = \"1\";\n\n    /// @notice The EIP-712 domain type hash. Exposed for integrators recomputing\n    /// the domain separator off-chain.\n    bytes32 public constant DOMAIN_TYPE_HASH =\n        keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n\n    /// @notice The EIP-712 Order type hash — the SAME one used to build the order\n    /// struct hash. Exposed so off-chain signers/integrators hash orders\n    /// identically without re-declaring the type string.\n    bytes32 public constant ORDER_TYPE_HASH = OrderLib.TYPE_HASH;\n\n    /// @notice The `buyToken` sentinel that pays out native ETH (`0xEeee…eEeE`).\n    /// Exposed so integrators build native-ETH-buy orders against the exact value\n    /// the protocol recognizes.\n    address public constant BUY_ETH = OrderLib.BUY_ETH;\n\n    // --------------------------------------------------------------- storage\n\n    /// @dev The Executor — the dynamic `delegatecall` routing layer holding the\n    /// working buffers. Deployed by this Gateway in the constructor (immutable\n    /// cross-reference) and driven over plain CALLs (`runModule`/`payOut`/\n    /// `payOutEth`). A separate address on purpose: a module running AS the\n    /// Executor can neither forge this contract's auth slots nor clear its lock.\n    Executor public immutable executor;\n\n    /// @dev The manager-curated solver allow-list gating settle. DEPLOYED BY this\n    /// Gateway in the constructor (with `solverManager` as manager) and held\n    /// immutable (code-baked, not a storage slot), so a module-as-Executor cannot\n    /// rewrite the reference and `onlySolver` always queries the real list.\n    SolverList public immutable solverList;\n\n    /// @dev The canonical Interaction Module — the default `mid` routing target,\n    /// DEPLOYED BY this Gateway alongside the Executor so its address is\n    /// discoverable here. Bound to the Executor (the only address that can recover\n    /// funds accidentally sent to it). The Gateway never calls it; solvers\n    /// reference it as the default routing module.\n    InteractionModule public immutable interactionModule;\n\n    /// @dev Domain separator cached at deployment.\n    bytes32 private immutable cachedDomainSeparator;\n\n    /// @dev The chain id the cached domain separator was computed for.\n    uint256 private immutable cachedChainId;\n\n    /// @dev Transient (EIP-1153) reentrancy lock. Lives in THIS contract's\n    /// storage by design — a module running AS the Executor can clear any\n    /// Executor slot but cannot reach this account's slot (cross-account).\n    bool private transient locked;\n\n    /// @dev Filled amount per fill slot, keyed by `fillKey(orderDigest, owner)`\n    /// (NOT the digest alone — the order has no owner field, so two owners with\n    /// identical params must not share fill state). `type(uint256).max` =\n    /// invalidated.\n    mapping(bytes32 => uint256) public filledAmount;\n\n    /// @dev On-chain order authorizations (scheme 3), keyed by the same\n    /// `fillKey(orderDigest, owner)` as fills (owner-scoped). `true` iff `owner`\n    /// called `setPreSignature(orderDigest, true)` — lets a contract / Safe owner\n    /// authorize by transaction instead of an off-chain signature.\n    mapping(bytes32 => bool) public preSignatures;\n\n    /// @dev A fully-validated trade captured in memory during verification and\n    /// consumed by pull + pay. Every field is derived from the SIGNED order and\n    /// the cross-mult-bound executed amounts — nothing is read from the Executor,\n    /// so a module cannot rewrite an amount or recipient between verify and pay.\n    struct Verified {\n        bytes32 digest;\n        address owner;\n        address sellToken;\n        address buyToken;\n        address receiver;\n        uint256 executedSellAmount;\n        uint256 executedBuyAmount;\n    }\n\n    /// @dev Gateway is the deploy root: it deploys the `SolverList` (with\n    /// `solverManager` as its manager), the Executor (with itself as the immutable\n    /// counterparty), and the `InteractionModule` (bound to that Executor) in its\n    /// constructor. All cross-references end up immutable and consistent; the\n    /// EIP-712 domain binds to `address(this)`.\n    constructor(address solverManager) {\n        solverList = new SolverList(solverManager);\n        executor = new Executor(address(this));\n        interactionModule = new InteractionModule(address(executor));\n        cachedChainId = block.chainid;\n        cachedDomainSeparator = computeDomainSeparator();\n    }\n\n    // ------------------------------------------------------------- modifiers\n\n    /// @dev Wall 3 — the reentrancy lock (this contract's own slot), held across\n    /// the whole settle span. Rejects the second settle from any caller,\n    /// including the Executor identity a module assumes during a phase.\n    modifier nonReentrant() {\n        if (locked) {\n            revert Reentrancy();\n        }\n        locked = true;\n        _;\n        locked = false;\n    }\n\n    /// @dev Wall 2 — restricts settle to an allow-listed solver. The Executor is\n    /// not allow-listed, so a re-entering module (running AS the Executor) is\n    /// rejected on identity. Queries the code-baked `solverList`.\n    modifier onlySolver() {\n        if (!solverList.isSolver(msg.sender)) {\n            revert NotSolver();\n        }\n        _;\n    }\n\n    /// @dev Wall 1 — the hardcoded guard, independent of SolverList state: the\n    /// Executor can never call settle, even if a manager mis-adds it. A module\n    /// re-entering settle mid-phase runs AS the Executor, so `msg.sender ==\n    /// address(executor)` is rejected here. The primary structural guarantee.\n    modifier notExecutor() {\n        if (msg.sender == address(executor)) {\n            revert ForbiddenSolver();\n        }\n        _;\n    }\n\n    // ----------------------------------------------------------------- views\n\n    /// @dev EIP-712 domain separator; recomputed iff the chain id changed since\n    /// deployment (fork-replay safety).\n    function domainSeparator() public view returns (bytes32) {\n        return block.chainid == cachedChainId ? cachedDomainSeparator : computeDomainSeparator();\n    }\n\n    /// @dev Filled amount for the (orderDigest, owner) fill slot.\n    function filled(bytes32 orderDigest, address owner) external view returns (uint256) {\n        return filledAmount[fillKey(orderDigest, owner)];\n    }\n\n    /// @notice The EIP-712 order digest this Gateway signs and settles for\n    /// `order`: `keccak256(\"\\x19\\x01\" || domainSeparator() || structHash)`. The\n    /// canonical helper for signers (the digest to sign for schemes 0/1) and for\n    /// integrators/indexers (the digest to query `filled`/`preSigned`) — so the\n    /// hashing is never re-implemented off-chain and can't drift.\n    function hashOrder(OrderLib.Order calldata order) external view returns (bytes32) {\n        return OrderLib.hash(order, domainSeparator());\n    }\n\n    /// @notice Whether `owner` has an on-chain pre-signature (scheme 3) for\n    /// `orderDigest`. The ergonomic mirror of `filled` for the pre-sign map.\n    function preSigned(bytes32 orderDigest, address owner) external view returns (bool) {\n        return preSignatures[fillKey(orderDigest, owner)];\n    }\n\n    /// @notice Packs an order `meta` word from its fields: `validTo` (unix\n    /// expiry), `partiallyFillable`, and the 16-byte `appDataHash`. Convenience so\n    /// integrators encode `meta` against the exact layout the protocol enforces.\n    function packMeta(uint32 validTo_, bool partiallyFillable_, bytes16 appDataHash_)\n        external\n        pure\n        returns (uint256)\n    {\n        return OrderLib.packMeta(validTo_, partiallyFillable_, appDataHash_);\n    }\n\n    /// @notice Decodes the `validTo` expiry timestamp from a `meta` word.\n    function metaValidTo(uint256 meta) external pure returns (uint256) {\n        return OrderLib.validTo(meta);\n    }\n\n    /// @notice Decodes the `partiallyFillable` flag from a `meta` word.\n    function metaPartiallyFillable(uint256 meta) external pure returns (bool) {\n        return OrderLib.isPartiallyFillable(meta);\n    }\n\n    /// @notice Decodes the `appDataHash` commitment from a `meta` word.\n    function metaAppDataHash(uint256 meta) external pure returns (bytes16) {\n        return OrderLib.appDataHash(meta);\n    }\n\n    // ------------------------------------------------------ order management\n\n    /// @dev Invalidates the caller's fill slot for `orderDigest` (owner-scoped).\n    function invalidateOrder(bytes32 orderDigest) external {\n        filledAmount[fillKey(orderDigest, msg.sender)] = type(uint256).max;\n        emit OrderInvalidated(msg.sender, orderDigest);\n    }\n\n    /// @dev Sets or clears the caller's on-chain pre-signature for `orderDigest`\n    /// (scheme 3, owner-scoped by `msg.sender`); only authorizes — every other\n    /// check still runs on settle. Neither the Gateway nor the Executor may\n    /// pre-sign for itself, preserving that neither is ever an order owner (an\n    /// Executor-owned order would \"sell\" buffer tokens). Single SSTORE, no\n    /// external call, so no guard needed; a module reaching it mid-settle lands\n    /// on its own slot, never a victim's.\n    function setPreSignature(bytes32 orderDigest, bool signed) external {\n        if (msg.sender == address(this) || msg.sender == address(executor)) {\n            revert SelfPreSignForbidden();\n        }\n        preSignatures[fillKey(orderDigest, msg.sender)] = signed;\n        emit PreSignatureSet(msg.sender, orderDigest, signed);\n    }\n\n    // ------------------------------------------------------- stray-fund recovery\n    //\n    // The Gateway has no token-out path in normal operation — it custodies\n    // nothing (the sole user-fund movement, `_pull`, lands the sell in the\n    // EXECUTOR). So any ERC20 mis-sent to the Gateway, or ETH force-fed via\n    // `selfdestruct` (the Gateway is non-payable, so ETH cannot arrive normally),\n    // would otherwise be permanently stuck. These solver-gated entries sweep ONLY\n    // this contract's OWN balance to a chosen recipient. (Stray funds resting on\n    // the Executor are recoverable by a solver via a `settle([], mid)` whose `mid`\n    // moves the Executor's balance — no dedicated Executor sweep is needed.)\n    //\n    // SAFETY: there is NO `from`/source parameter and NO `transferFrom` — a\n    // `transferFrom`-shaped variant would be a catastrophic allowance drain\n    // (users approve this Gateway `type(uint256).max`). Sweeping the Gateway's own\n    // balance can only ever move accidental funds. Gated with the EXACT\n    // `notExecutor onlySolver nonReentrant` order `settle*` uses (the lock here is\n    // correct and required: it shares the settle lock, so a `recover*` can never\n    // interleave with a settle, and the Executor identity is rejected at wall 1).\n\n    /// @notice Sweeps this Gateway's full ERC20 `token` balance to `to`. Solver\n    /// only; the Executor identity is rejected (`ForbiddenSolver`). Reverts\n    /// `NothingToRecover` on a zero balance (no no-op transfer / event). Moves\n    /// ONLY this Gateway's own (stray) balance — there is no `from` parameter and\n    /// no `transferFrom`, so a user's standing approval is untouchable here.\n    function recoverERC20(address token, address to) external notExecutor onlySolver nonReentrant {\n        uint256 bal = IERC20(token).balanceOf(address(this));\n        if (bal == 0) {\n            revert NothingToRecover();\n        }\n        SafeERC20.safeTransfer(token, to, bal);\n        emit Recovered(token, to, bal);\n    }\n\n    /// @notice Sweeps this Gateway's full native ETH balance to `to`. Solver only.\n    /// Reverts `NothingToRecover` on a zero balance. The Gateway is NON-PAYABLE\n    /// (no `receive`/`fallback`), so a normal ETH send reverts — this only ever\n    /// rescues `selfdestruct`-force-fed ETH.\n    function recoverEth(address to) external notExecutor onlySolver nonReentrant {\n        uint256 bal = address(this).balance;\n        if (bal == 0) {\n            revert NothingToRecover();\n        }\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool ok,) = to.call{value: bal}(\"\");\n        if (!ok) {\n            revert EthRecoveryFailed();\n        }\n        emit EthRecovered(to, bal);\n    }\n\n    // ----------------------------------------------------------- settlement\n    //\n    // Four variants of the locked settle. The `mid` routing phase (the swap\n    // spine, run between pull and pay) is ALWAYS present — a settle with no mid\n    // is not a supported shape — so the variants differ only by the OPTIONAL\n    // `top` (pre-pull) and `bot` (post-pay) phases: mid / top+mid / mid+bot /\n    // top+mid+bot. EVERY variant is gated `notExecutor onlySolver nonReentrant`\n    // (this exact left-to-right order: walls-first-lock-last — the caller's\n    // identity is rejected at entry, the lock is the redundant backstop; do NOT\n    // reorder). The lock spans the whole body including every `executor.runModule`\n    // delegate. Phase order is fixed:\n    //   _verify -> [top] -> _pull -> mid -> _pay -> [bot]\n    // so `top` (before pull) cannot change the pull and `bot` (after pay) cannot\n    // claw back. Gateway only CALLs `executor.runModule` — it never delegatecalls.\n    // `_verify`/`_pull`/`_pay` carry the security-critical core (verification,\n    // the sole user-fund movement, and memory-derived payouts).\n\n    /// @notice _verify -> _pull -> mid -> _pay.\n    function settle(OrderLib.Trade[] calldata trades, Module calldata mid)\n        external\n        notExecutor\n        onlySolver\n        nonReentrant\n    {\n        Verified[] memory v = _verify(trades);\n        _pull(v);\n        executor.runModule(mid);\n        _pay(v);\n    }\n\n    /// @notice _verify -> top -> _pull -> mid -> _pay.\n    function settleT(OrderLib.Trade[] calldata trades, Module calldata top, Module calldata mid)\n        external\n        notExecutor\n        onlySolver\n        nonReentrant\n    {\n        Verified[] memory v = _verify(trades);\n        executor.runModule(top);\n        _pull(v);\n        executor.runModule(mid);\n        _pay(v);\n    }\n\n    /// @notice _verify -> _pull -> mid -> _pay -> bot.\n    function settleB(OrderLib.Trade[] calldata trades, Module calldata mid, Module calldata bot)\n        external\n        notExecutor\n        onlySolver\n        nonReentrant\n    {\n        Verified[] memory v = _verify(trades);\n        _pull(v);\n        executor.runModule(mid);\n        _pay(v);\n        executor.runModule(bot);\n    }\n\n    /// @notice _verify -> top -> _pull -> mid -> _pay -> bot.\n    function settleTB(OrderLib.Trade[] calldata trades, Module calldata top, Module calldata mid, Module calldata bot)\n        external\n        notExecutor\n        onlySolver\n        nonReentrant\n    {\n        Verified[] memory v = _verify(trades);\n        executor.runModule(top);\n        _pull(v);\n        executor.runModule(mid);\n        _pay(v);\n        executor.runModule(bot);\n    }\n\n    // ------------------------------------------------------------- internals\n\n    /// @dev Validates every trade and records fill state (effects BEFORE any\n    /// external call), returning the in-memory list pull + pay consume. Every\n    /// captured value comes from the SIGNED order and the cross-mult-bound\n    /// executed amounts — nothing from the Executor.\n    function _verify(OrderLib.Trade[] calldata trades) private returns (Verified[] memory verified) {\n        uint256 numTrades = trades.length;\n        verified = new Verified[](numTrades);\n        if (numTrades == 0) {\n            return verified;\n        }\n\n        bytes32 separator = domainSeparator();\n\n        for (uint256 i; i < numTrades; ++i) {\n            OrderLib.Trade calldata trade = trades[i];\n            OrderLib.Order calldata order = trade.order;\n\n            // Meta sanity: reserved bits zero, not expired.\n            OrderLib.requireReservedZero(order.meta);\n            // solhint-disable-next-line not-rely-on-time\n            if (OrderLib.validTo(order.meta) < block.timestamp) {\n                revert OrderExpired();\n            }\n\n            // Zero-amount drain killer.\n            if (order.sellAmount == 0 || order.buyAmount == 0 || trade.executedSellAmount == 0) {\n                revert ZeroAmount();\n            }\n\n            // Recover the owner from the signature.\n            bytes32 digest = OrderLib.hash(order, separator);\n            address owner = recoverOwner(digest, trade.signature);\n\n            // Fill accounting — effects before any external call.\n            bytes32 key = fillKey(digest, owner);\n            uint256 alreadyFilled = filledAmount[key];\n            if (!OrderLib.isPartiallyFillable(order.meta)) {\n                if (alreadyFilled != 0) {\n                    revert OrderAlreadyFilled();\n                }\n                if (trade.executedSellAmount != order.sellAmount) {\n                    revert FillOrKillMismatch();\n                }\n                filledAmount[key] = order.sellAmount;\n            } else {\n                // Rejects invalidated/fully-filled, then enforces\n                // executedSellAmount <= sellAmount - alreadyFilled.\n                if (alreadyFilled >= order.sellAmount || trade.executedSellAmount > order.sellAmount - alreadyFilled) {\n                    revert OrderOverfill();\n                }\n                filledAmount[key] = alreadyFilled + trade.executedSellAmount;\n            }\n\n            // Limit by cross-multiplication (no clearing price, no division).\n            // 0.8 checked mul reverts on absurd (~>2^128) products — safe.\n            if (trade.executedBuyAmount * order.sellAmount < order.buyAmount * trade.executedSellAmount) {\n                revert LimitNotMet();\n            }\n\n            // Capture the signed-order-derived trade for pull + pay.\n            verified[i] = Verified({\n                digest: digest,\n                owner: owner,\n                sellToken: order.sellToken,\n                buyToken: order.buyToken,\n                receiver: order.receiver == address(0) ? owner : order.receiver,\n                executedSellAmount: trade.executedSellAmount,\n                executedBuyAmount: trade.executedBuyAmount\n            });\n        }\n    }\n\n    /// @dev The protocol's ONLY movement of a user's approved funds: pulls each\n    /// trade's sell STRAIGHT from the owner into the Executor via a private\n    /// `safeTransferFrom`. Private and reachable only from a locked, verified\n    /// settle variant — there is no standalone pull. Users approved THIS Gateway;\n    /// the sell lands where the buffers live and the modules run.\n    function _pull(Verified[] memory verified) private {\n        for (uint256 i; i < verified.length; ++i) {\n            SafeERC20.safeTransferFrom(\n                verified[i].sellToken, verified[i].owner, address(executor), verified[i].executedSellAmount\n            );\n        }\n    }\n\n    /// @dev Pays each trade's executed buy amount to its receiver and emits the\n    /// event. Amounts/recipients are read from the `verified` MEMORY (never\n    /// Executor storage, never a phase return value), sourced from the Executor's\n    /// inventory. A short payout reverts the whole settle (atomic). The Gateway\n    /// only directs the transfer; the funds move from the contract holding them.\n    function _pay(Verified[] memory verified) private {\n        for (uint256 i; i < verified.length; ++i) {\n            Verified memory v = verified[i];\n\n            if (v.buyToken == OrderLib.BUY_ETH) {\n                executor.payOutEth(v.receiver, v.executedBuyAmount);\n            } else {\n                executor.payOut(v.buyToken, v.receiver, v.executedBuyAmount);\n            }\n\n            emit Trade(v.owner, v.sellToken, v.buyToken, v.receiver, v.digest, v.executedSellAmount, v.executedBuyAmount);\n        }\n    }\n\n    /// @dev Verifies `signature` over `orderDigest` and returns the owner.\n    /// Encoding: one scheme byte then the payload —\n    ///  - 0: EIP-712 ECDSA, payload `r||s||v` (65 bytes), `ecrecover` on digest;\n    ///  - 1: eth_sign ECDSA, `ecrecover` on the personal-message hash of digest;\n    ///  - 2: EIP-1271, payload = 20-byte owner address then the contract sig;\n    ///  - 3: pre-sign, payload = exactly the 20-byte owner address (no sig;\n    ///    authorized by a prior `setPreSignature`).\n    function recoverOwner(bytes32 orderDigest, bytes calldata signature) private view returns (address owner) {\n        if (signature.length == 0) {\n            revert MalformedSignature();\n        }\n        uint256 scheme = uint8(signature[0]);\n        bytes calldata payload = signature[1:];\n\n        if (scheme == 0) {\n            owner = ecdsaRecover(orderDigest, payload);\n        } else if (scheme == 1) {\n            bytes32 ethSignDigest = keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", orderDigest));\n            owner = ecdsaRecover(ethSignDigest, payload);\n        } else if (scheme == 2) {\n            if (payload.length < 20) {\n                revert MalformedSignature();\n            }\n            // owner = address(payload[0:20])\n            // solhint-disable-next-line no-inline-assembly\n            assembly (\"memory-safe\") {\n                owner := shr(96, calldataload(payload.offset))\n            }\n            if (IERC1271(owner).isValidSignature(orderDigest, payload[20:]) != IERC1271.isValidSignature.selector) {\n                revert InvalidEip1271Signature();\n            }\n        } else if (scheme == 3) {\n            // Strict length: payload is exactly the 20-byte owner, no trailing\n            // sig (unlike scheme 2). Authorization is the prior on-chain pre-sign.\n            if (payload.length != 20) {\n                revert MalformedSignature();\n            }\n            // owner = address(payload[0:20])\n            // solhint-disable-next-line no-inline-assembly\n            assembly (\"memory-safe\") {\n                owner := shr(96, calldataload(payload.offset))\n            }\n            if (!preSignatures[fillKey(orderDigest, owner)]) {\n                revert NotPreSigned();\n            }\n        } else {\n            revert UnknownSignatureScheme();\n        }\n    }\n\n    /// @dev Recovers an ECDSA signer from a packed `r||s||v` payload, rejecting\n    /// zero-address recoveries. NO EIP-2 low-`s` / `v∈{27,28}` canonicalization:\n    /// signature malleability is harmless ONLY because fill state is keyed by\n    /// `fillKey(orderDigest, owner)` — a malleated twin recovers the SAME owner\n    /// over the SAME digest → the SAME already-consumed slot — never by signature\n    /// bytes. Any future change MUST keep fill/replay state keyed on (digest, owner).\n    function ecdsaRecover(bytes32 digest, bytes calldata payload) private pure returns (address signer) {\n        if (payload.length != 65) {\n            revert MalformedSignature();\n        }\n\n        bytes32 r;\n        bytes32 s;\n        uint8 v;\n        // solhint-disable-next-line no-inline-assembly\n        assembly (\"memory-safe\") {\n            r := calldataload(payload.offset)\n            s := calldataload(add(payload.offset, 32))\n            v := shr(248, calldataload(add(payload.offset, 64)))\n        }\n\n        signer = ecrecover(digest, v, r, s);\n        if (signer == address(0)) {\n            revert InvalidSignature();\n        }\n    }\n\n    /// @notice The fill-slot key for an (orderDigest, owner) pair —\n    /// `keccak256(orderDigest || owner)`. Exposed so integrators read the raw\n    /// `filledAmount`/`preSignatures` maps (or precompute the slot) consistently.\n    function fillKey(bytes32 orderDigest, address owner) public pure returns (bytes32) {\n        return keccak256(abi.encodePacked(orderDigest, owner));\n    }\n\n    /// @dev Computes the EIP-712 domain separator, binding to `address(this)`.\n    function computeDomainSeparator() private view returns (bytes32) {\n        return keccak256(\n            abi.encode(\n                DOMAIN_TYPE_HASH,\n                keccak256(bytes(DOMAIN_NAME)),\n                keccak256(bytes(DOMAIN_VERSION)),\n                block.chainid,\n                address(this)\n            )\n        );\n    }\n}\n","deployed_bytecode":"0x608060405234801561000f575f5ffd5b50600436106101b0575f3560e01c8063acb8cc49116100f3578063e95c41ca11610093578063f698da251161006e578063f698da25146104c2578063f983248b146104ca578063fddff57e146104e5578063fe6cecc9146104f8575f5ffd5b8063e95c41ca1461047a578063eb8fb2681461049c578063ef3e58ca146104af575f5ffd5b8063c0993eea116100ce578063c0993eea146103f2578063c34c08e514610419578063cf615a7314610440578063d985df2314610467575f5ffd5b8063acb8cc491461037c578063b91611f4146103b8578063bab0e52e146103df575f5ffd5b80635baf49571161015e578063796f077b11610139578063796f077b146102ea5780637bca7d301461033357806382c174d014610346578063886f039a14610369575f5ffd5b80635baf4957146102805780635f190940146102c45780637504db3e146102d7575f5ffd5b806328c131a61161018e57806328c131a61461020e5780633ff21e0c146102215780634ec519191461026d575f5ffd5b806307e4841c146101b45780630b20b7bc146101da57806323790419146101f9575b5f5ffd5b6101c76101c2366004612b62565b61050b565b6040519081526020015b60405180910390f35b6101c76101e8366004612b8c565b5f6020819052908152604090205481565b61020c610207366004612c01565b61052f565b005b61020c61021c366004612cbf565b610917565b6102487f000000000000000000000000a2e3c5205a23dd7176b1dbcf240120be3b79773781565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d1565b61020c61027b366004612b8c565b610bbc565b61029361028e366004612b8c565b610c4d565b6040517fffffffffffffffffffffffffffffffff0000000000000000000000000000000090911681526020016101d1565b61020c6102d2366004612d28565b610c76565b61020c6102e5366004612dbc565b610fbd565b6103266040518060400160405280600681526020017f4f70636f6465000000000000000000000000000000000000000000000000000081525081565b6040516101d19190612ddc565b61020c610341366004612d28565b6112c5565b610359610354366004612b62565b61160b565b60405190151581526020016101d1565b61020c610377366004612e2f565b611633565b6103266040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b6101c77fbe76dd4d42322ae2631eaa627d589ce5352fec12b7d61e7fc048d240a538a60d81565b6101c76103ed366004612b62565b611954565b6101c77f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6102487f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa2881565b6102487f00000000000000000000000061ad6d3d8b97b9afa9cf48c4520b0c35a02a459681565b6101c7610475366004612e57565b6119b4565b610359610488366004612b8c565b60016020525f908152604090205460ff1681565b61020c6104aa366004612e7d565b6119c6565b6101c76104bd366004612eab565b611ace565b6101c7611ae2565b61024873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b6101c76104f3366004612b8c565b611c30565b610359610506366004612b8c565b611c3d565b5f5f5f6105188585611954565b81526020019081526020015f205490505b92915050565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa2816330361059e576040517f2525631800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f02cc250d0000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000061ad6d3d8b97b9afa9cf48c4520b0c35a02a459673ffffffffffffffffffffffffffffffffffffffff16906302cc250d90602401602060405180830381865afa158015610626573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061064a9190612f1f565b610680576040517fc139eabd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff5f5c16156106bc576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015f805c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168217905d505f6106f38686611c4d565b6040517f5cbbd5a900000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa281690635cbbd5a990610768908790600401612f81565b5f604051808303815f87803b15801561077f575f5ffd5b505af1158015610791573d5f5f3e3d5ffd5b5050505061079e816120c9565b6040517f5cbbd5a900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa281690635cbbd5a990610810908690600401612f81565b5f604051808303815f87803b158015610827575f5ffd5b505af1158015610839573d5f5f3e3d5ffd5b5050505061084681612163565b6040517f5cbbd5a900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa281690635cbbd5a9906108b8908590600401612f81565b5f604051808303815f87803b1580156108cf575f5ffd5b505af11580156108e1573d5f5f3e3d5ffd5b505f93505050815c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169050815d505050505050565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa28163303610986576040517f2525631800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f02cc250d0000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000061ad6d3d8b97b9afa9cf48c4520b0c35a02a459673ffffffffffffffffffffffffffffffffffffffff16906302cc250d90602401602060405180830381865afa158015610a0e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a329190612f1f565b610a68576040517fc139eabd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff5f5c1615610aa4576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015f805c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168217905d505f610adb8484611c4d565b9050610ae6816120c9565b6040517f5cbbd5a900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa281690635cbbd5a990610b58908590600401612f81565b5f604051808303815f87803b158015610b6f575f5ffd5b505af1158015610b81573d5f5f3e3d5ffd5b50505050610b8e81612163565b505f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815c16815d50505050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f5f610be98433611954565b81526020019081526020015f20819055503373ffffffffffffffffffffffffffffffffffffffff167feca8ae6c58cd627e31d2272ad956830428b7087cef26fc61d7605ba56b529dcc82604051610c4291815260200190565b60405180910390a250565b5f7fffffffffffffffffffffffffffffffff000000000000000000000000000000008216610529565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa28163303610ce5576040517f2525631800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f02cc250d0000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000061ad6d3d8b97b9afa9cf48c4520b0c35a02a459673ffffffffffffffffffffffffffffffffffffffff16906302cc250d90602401602060405180830381865afa158015610d6d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d919190612f1f565b610dc7576040517fc139eabd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff5f5c1615610e03576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015f805c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168217905d505f610e3a8585611c4d565b9050610e45816120c9565b6040517f5cbbd5a900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa281690635cbbd5a990610eb7908690600401612f81565b5f604051808303815f87803b158015610ece575f5ffd5b505af1158015610ee0573d5f5f3e3d5ffd5b50505050610eed81612163565b6040517f5cbbd5a900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa281690635cbbd5a990610f5f908590600401612f81565b5f604051808303815f87803b158015610f76575f5ffd5b505af1158015610f88573d5f5f3e3d5ffd5b505f93505050815c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169050815d5050505050565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa2816330361102c576040517f2525631800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f02cc250d0000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000061ad6d3d8b97b9afa9cf48c4520b0c35a02a459673ffffffffffffffffffffffffffffffffffffffff16906302cc250d90602401602060405180830381865afa1580156110b4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110d89190612f1f565b61110e576040517fc139eabd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff5f5c161561114a576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015f805c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168217905d50475f8190036111b1576040517faba3a54800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8273ffffffffffffffffffffffffffffffffffffffff16826040515f6040518083038185875af1925050503d805f8114611207576040519150601f19603f3d011682016040523d82523d5f602084013e61120c565b606091505b5050905080611247576040517fd52fecf700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff167fd01205615e35ba1dd087bd6dac5922e0370961b3726c247c078cd59baae5770e8360405161128f91815260200190565b60405180910390a2505f90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815c16815d5050565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa28163303611334576040517f2525631800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f02cc250d0000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000061ad6d3d8b97b9afa9cf48c4520b0c35a02a459673ffffffffffffffffffffffffffffffffffffffff16906302cc250d90602401602060405180830381865afa1580156113bc573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113e09190612f1f565b611416576040517fc139eabd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff5f5c1615611452576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015f805c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168217905d505f6114898585611c4d565b6040517f5cbbd5a900000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa281690635cbbd5a9906114fe908690600401612f81565b5f604051808303815f87803b158015611515575f5ffd5b505af1158015611527573d5f5f3e3d5ffd5b50505050611534816120c9565b6040517f5cbbd5a900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa281690635cbbd5a9906115a6908590600401612f81565b5f604051808303815f87803b1580156115bd575f5ffd5b505af11580156115cf573d5f5f3e3d5ffd5b505050506115dc81612163565b505f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815c16815d5050505050565b5f60015f6116198585611954565b815260208101919091526040015f205460ff169392505050565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa281633036116a2576040517f2525631800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f02cc250d0000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000061ad6d3d8b97b9afa9cf48c4520b0c35a02a459673ffffffffffffffffffffffffffffffffffffffff16906302cc250d90602401602060405180830381865afa15801561172a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061174e9190612f1f565b611784576040517fc139eabd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff5f5c16156117c0576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015f805c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168217905d506040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611856573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061187a9190613025565b9050805f036118b5576040517faba3a54800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118c0838383612432565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167ffff3b3844276f57024e0b42afec1a37f75db36511e43819a4f2a63ab7862b6488360405161191f91815260200190565b60405180910390a3505f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815c16815d505050565b5f828260405160200161199692919091825260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602082015260340190565b60405160208183030381529060405280519060200120905092915050565b5f610529826119c1611ae2565b6124a2565b33301480611a0957503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa2816145b15611a40576040517f4e726bd900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060015f611a4e8533611954565b815260208082019290925260409081015f2080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169315159390931790925581518481528315159181019190915233917fe5e09c712e9db70ee7241ab7dd662edc18050d7e0332cf6f2d073cd5a4f5818d910160405180910390a25050565b5f611ada848484612515565b949350505050565b5f7f00000000000000000000000000000000000000000000000000000000000000014614611c0b5750604080518082018252600681527f4f70636f6465000000000000000000000000000000000000000000000000000060209182015281518083018352600181527f31000000000000000000000000000000000000000000000000000000000000009082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527f5ada70868a718a865a2fd9ca85a7edfc69bbeff05c34eeabb718adec794eaa6b818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a0808301919091528351808303909101815260c0909101909252815191012090565b507f90303cf25873aeef29396fca0b1a0c02b4b86695cc5597c12d9622690a65193490565b5f63ffffffff8216610529565b5f64010000000082161515610529565b6060818067ffffffffffffffff811115611c6957611c6961303c565b604051908082528060200260200182016040528015611ced57816020015b6040805160e0810182525f8082526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181611c875790505b509150805f03611cfd5750610529565b5f611d06611ae2565b90505f5b828110156120c05736868683818110611d2557611d25613069565b9050602002810190611d379190613096565b905080611d4760a082013561255d565b4263ffffffff60a0830135161015611d8b576040517fc56873ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608101351580611d9e57506080810135155b80611dab575060c0820135155b15611de2576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611ded82866124a2565b90505f611e0782611e026101008701876130d2565b6125b9565b90505f611e148383611954565b5f8181526020819052604090205490915064010000000060a086013516611ec7578015611e6d576040517fee3b3d4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84606001358660c0013514611eae576040517fdb46982600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f82815260208190526040902060608601359055611f3e565b846060013581101580611eea5750611ee3816060870135613160565b8660c00135115b15611f21576040517f0280215600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611f2f60c087013582613173565b5f838152602081905260409020555b611f5060c08701356080870135613186565b611f62606087013560e0890135613186565b1015611f9a576040517f74f7ce3600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040518060e001604052808581526020018473ffffffffffffffffffffffffffffffffffffffff168152602001865f016020810190611fd99190612dbc565b73ffffffffffffffffffffffffffffffffffffffff1681526020018660200160208101906120079190612dbc565b73ffffffffffffffffffffffffffffffffffffffff1681526020015f6120336060890160408a01612dbc565b73ffffffffffffffffffffffffffffffffffffffff16146120635761205e6060880160408901612dbc565b612065565b845b73ffffffffffffffffffffffffffffffffffffffff1681526020018760c0013581526020018760e001358152508a88815181106120a4576120a4613069565b6020026020010181905250505050505050806001019050611d0a565b50505092915050565b5f5b815181101561215f576121578282815181106120e9576120e9613069565b60200260200101516040015183838151811061210757612107613069565b6020026020010151602001517f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa2885858151811061214657612146613069565b602002602001015160a001516128bb565b6001016120cb565b5050565b5f5b815181101561215f575f82828151811061218157612181613069565b6020026020010151905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff16816060015173ffffffffffffffffffffffffffffffffffffffff16036122a357608081015160c08201516040517f068d279900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa28169263068d2799926122719260040173ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b5f604051808303815f87803b158015612288575f5ffd5b505af115801561229a573d5f5f3e3d5ffd5b5050505061235e565b6060810151608082015160c08301516040517fa00c695100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9384166004820152918316602483015260448201527f0000000000000000000000002fd4b35906550f21f4d779f8ab87e449cab9fa289091169063a00c6951906064015f604051808303815f87803b158015612347575f5ffd5b505af1158015612359573d5f5f3e3d5ffd5b505050505b806060015173ffffffffffffffffffffffffffffffffffffffff16816040015173ffffffffffffffffffffffffffffffffffffffff16826020015173ffffffffffffffffffffffffffffffffffffffff167f207bdd4bc09afcc562d729418fb78ff66daae1d18623e0f5d2ebdcb0091039718460800151855f01518660a001518760c00151604051612421949392919073ffffffffffffffffffffffffffffffffffffffff94909416845260208401929092526040830152606082015260800190565b60405180910390a450600101612165565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000080825273ffffffffffffffffffffffffffffffffffffffff8416600483015260248201839052905f8060448382895af1612492573d5f5f3e3d5ffd5b5061249c84612934565b50505050565b6040517fbe76dd4d42322ae2631eaa627d589ce5352fec12b7d61e7fc048d240a538a60d8082525f9160c085602083013760e081207f1901000000000000000000000000000000000000000000000000000000000000825284600283015280602283015250604281209250505092915050565b5f7fffffffffffffffffffffffffffffffff00000000000000000000000000000000821683612544575f61254b565b6401000000005b8563ffffffff16171790509392505050565b600161256b60216080613160565b6001901b6125799190613160565b602182901c16156125b6576040517fbb1d35e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f8181036125f3576040517f55a1e16e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f83835f81811061260657612606613069565b919091013560f81c91503690505f612621856001818961319d565b91509150825f0361263e57612637878383612a2a565b93506128b1565b826001036126a6576040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018890525f90605c0160405160208183030381529060405280519060200120905061269e818484612a2a565b9450506128b1565b826002036127e05760148110156126e9576040517f55a1e16e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b813560601c93507f1626ba7e0000000000000000000000000000000000000000000000000000000084631626ba7e89612725856014818961319d565b6040518463ffffffff1660e01b8152600401612743939291906131c4565b602060405180830381865afa15801561275e573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061278291906131dd565b7fffffffff0000000000000000000000000000000000000000000000000000000016146127db576040517fae1500ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6128b1565b8260030361287f5760148114612822576040517f55a1e16e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b813560601c935060015f6128368987611954565b815260208101919091526040015f205460ff166127db576040517f763020c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f1bc11be100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050509392505050565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000080825273ffffffffffffffffffffffffffffffffffffffff85811660048401528416602483015260448201839052905f80606483828a5af1612923573d5f5f3e3d5ffd5b5061292d85612934565b5050505050565b5f3d801561294d576020811461296c5760039150612978565b823b15600181146129615760019250612966565b600292505b50612978565b60205f5f3e5f51151591505b5080600103612985575050565b805f036129be576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806002036129f8576040517f09ee12d500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f30ae1b4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60418214612a65576040517f55a1e16e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080515f815260208082018084528790528583013560f81c92820183905285356060830181905290860135608083018190529092909160019060a0016020604051602081039080840390855afa158015612ac2573d5f5f3e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015194505073ffffffffffffffffffffffffffffffffffffffff84166128b1576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114612b5d575f5ffd5b919050565b5f5f60408385031215612b73575f5ffd5b82359150612b8360208401612b3a565b90509250929050565b5f60208284031215612b9c575f5ffd5b5035919050565b5f5f83601f840112612bb3575f5ffd5b50813567ffffffffffffffff811115612bca575f5ffd5b6020830191508360208260051b8501011115612be4575f5ffd5b9250929050565b5f60408284031215612bfb575f5ffd5b50919050565b5f5f5f5f5f60808688031215612c15575f5ffd5b853567ffffffffffffffff811115612c2b575f5ffd5b612c3788828901612ba3565b909650945050602086013567ffffffffffffffff811115612c56575f5ffd5b612c6288828901612beb565b935050604086013567ffffffffffffffff811115612c7e575f5ffd5b612c8a88828901612beb565b925050606086013567ffffffffffffffff811115612ca6575f5ffd5b612cb288828901612beb565b9150509295509295909350565b5f5f5f60408486031215612cd1575f5ffd5b833567ffffffffffffffff811115612ce7575f5ffd5b612cf386828701612ba3565b909450925050602084013567ffffffffffffffff811115612d12575f5ffd5b612d1e86828701612beb565b9150509250925092565b5f5f5f5f60608587031215612d3b575f5ffd5b843567ffffffffffffffff811115612d51575f5ffd5b612d5d87828801612ba3565b909550935050602085013567ffffffffffffffff811115612d7c575f5ffd5b612d8887828801612beb565b925050604085013567ffffffffffffffff811115612da4575f5ffd5b612db087828801612beb565b91505092959194509250565b5f60208284031215612dcc575f5ffd5b612dd582612b3a565b9392505050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b5f5f60408385031215612e40575f5ffd5b612e4983612b3a565b9150612b8360208401612b3a565b5f60c0828403128015612e68575f5ffd5b509092915050565b80151581146125b6575f5ffd5b5f5f60408385031215612e8e575f5ffd5b823591506020830135612ea081612e70565b809150509250929050565b5f5f5f60608486031215612ebd575f5ffd5b833563ffffffff81168114612ed0575f5ffd5b92506020840135612ee081612e70565b915060408401357fffffffffffffffffffffffffffffffff0000000000000000000000000000000081168114612f14575f5ffd5b809150509250925092565b5f60208284031215612f2f575f5ffd5b8151612dd581612e70565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6020815273ffffffffffffffffffffffffffffffffffffffff612fa383612b3a565b1660208201525f60208301357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612fde575f5ffd5b830160208101903567ffffffffffffffff811115612ffa575f5ffd5b803603821315613008575f5ffd5b60408085015261301c606085018284612f3a565b95945050505050565b5f60208284031215613035575f5ffd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181126130c8575f5ffd5b9190910192915050565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613105575f5ffd5b83018035915067ffffffffffffffff82111561311f575f5ffd5b602001915036819003821315612be4575f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8181038181111561052957610529613133565b8082018082111561052957610529613133565b808202811582820484141761052957610529613133565b5f5f858511156131ab575f5ffd5b838611156131b7575f5ffd5b5050820193919092039150565b838152604060208201525f61301c604083018486612f3a565b5f602082840312156131ed575f5ffd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114612dd5575f5ffdfea264697066735822122007a15f89f35a69580d13cb302aaaf07c80690aceb653a09880a9de7dc8f0d03b64736f6c63430008230033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"cancun","libraries":{},"metadata":{"appendCBOR":true,"bytecodeHash":"ipfs","useLiteralContent":false},"optimizer":{"enabled":true,"runs":1000000},"outputSelection":{"*":{"":["*"],"*":["*"]}},"remappings":["forge-std/=lib/forge-std/src/"],"viaIR":false},"optimization_runs":1000000,"sourcify_repo_url":null,"decoded_constructor_args":[["0xF5512890d07a2f156D5d3481831905f30574C48F",{"internalType":"address","name":"solverManager","type":"address"}]],"compiler_version":"v0.8.35+commit.47b9dedd","is_verified_via_verifier_alliance":false,"verified_at":"2026-06-25T17:22:29.258549Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x610120604052348015610010575f5ffd5b50604051614fb0380380614fb083398101604081905261002f916101ff565b8060405161003c906101d8565b6001600160a01b039091168152602001604051809103905ff080158015610065573d5f5f3e3d5ffd5b506001600160a01b031660a0526040513090610080906101e5565b6001600160a01b039091168152602001604051809103905ff0801580156100a9573d5f5f3e3d5ffd5b506001600160a01b031660808190526040516100c4906101f2565b6001600160a01b039091168152602001604051809103905ff0801580156100ed573d5f5f3e3d5ffd5b506001600160a01b031660c05246610100526101cf60408051808201825260068152654f70636f646560d01b6020918201528151808301835260018152603160f81b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527f5ada70868a718a865a2fd9ca85a7edfc69bbeff05c34eeabb718adec794eaa6b818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a0808301919091528351808303909101815260c0909101909252815191012090565b60e0525061022c565b610ab88061356383390190565b6106c78061401b83390190565b6108ce806146e283390190565b5f6020828403121561020f575f5ffd5b81516001600160a01b0381168114610225575f5ffd5b9392505050565b60805160a05160c05160e051610100516132526103115f395f611ae501525f611c0e01525f61022601525f8181610445015281816105cc015281816109b401528181610d130152818161105a0152818161136201526116d001525f818161041e0152818161054601528181610733015281816107db015281816108830152818161092e01528181610b2301528181610c8d01528181610e8201528181610f2a01528181610fd4015281816112dc015281816114c9015281816115710152818161164a015281816119e7015281816121150152818161221d015261230401526132525ff3fe608060405234801561000f575f5ffd5b50600436106101b0575f3560e01c8063acb8cc49116100f3578063e95c41ca11610093578063f698da251161006e578063f698da25146104c2578063f983248b146104ca578063fddff57e146104e5578063fe6cecc9146104f8575f5ffd5b8063e95c41ca1461047a578063eb8fb2681461049c578063ef3e58ca146104af575f5ffd5b8063c0993eea116100ce578063c0993eea146103f2578063c34c08e514610419578063cf615a7314610440578063d985df2314610467575f5ffd5b8063acb8cc491461037c578063b91611f4146103b8578063bab0e52e146103df575f5ffd5b80635baf49571161015e578063796f077b11610139578063796f077b146102ea5780637bca7d301461033357806382c174d014610346578063886f039a14610369575f5ffd5b80635baf4957146102805780635f190940146102c45780637504db3e146102d7575f5ffd5b806328c131a61161018e57806328c131a61461020e5780633ff21e0c146102215780634ec519191461026d575f5ffd5b806307e4841c146101b45780630b20b7bc146101da57806323790419146101f9575b5f5ffd5b6101c76101c2366004612b62565b61050b565b6040519081526020015b60405180910390f35b6101c76101e8366004612b8c565b5f6020819052908152604090205481565b61020c610207366004612c01565b61052f565b005b61020c61021c366004612cbf565b610917565b6102487f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d1565b61020c61027b366004612b8c565b610bbc565b61029361028e366004612b8c565b610c4d565b6040517fffffffffffffffffffffffffffffffff0000000000000000000000000000000090911681526020016101d1565b61020c6102d2366004612d28565b610c76565b61020c6102e5366004612dbc565b610fbd565b6103266040518060400160405280600681526020017f4f70636f6465000000000000000000000000000000000000000000000000000081525081565b6040516101d19190612ddc565b61020c610341366004612d28565b6112c5565b610359610354366004612b62565b61160b565b60405190151581526020016101d1565b61020c610377366004612e2f565b611633565b6103266040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b6101c77fbe76dd4d42322ae2631eaa627d589ce5352fec12b7d61e7fc048d240a538a60d81565b6101c76103ed366004612b62565b611954565b6101c77f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6102487f000000000000000000000000000000000000000000000000000000000000000081565b6102487f000000000000000000000000000000000000000000000000000000000000000081565b6101c7610475366004612e57565b6119b4565b610359610488366004612b8c565b60016020525f908152604090205460ff1681565b61020c6104aa366004612e7d565b6119c6565b6101c76104bd366004612eab565b611ace565b6101c7611ae2565b61024873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b6101c76104f3366004612b8c565b611c30565b610359610506366004612b8c565b611c3d565b5f5f5f6105188585611954565b81526020019081526020015f205490505b92915050565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361059e576040517f2525631800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f02cc250d0000000000000000000000000000000000000000000000000000000081523360048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906302cc250d90602401602060405180830381865afa158015610626573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061064a9190612f1f565b610680576040517fc139eabd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff5f5c16156106bc576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015f805c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168217905d505f6106f38686611c4d565b6040517f5cbbd5a900000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690635cbbd5a990610768908790600401612f81565b5f604051808303815f87803b15801561077f575f5ffd5b505af1158015610791573d5f5f3e3d5ffd5b5050505061079e816120c9565b6040517f5cbbd5a900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690635cbbd5a990610810908690600401612f81565b5f604051808303815f87803b158015610827575f5ffd5b505af1158015610839573d5f5f3e3d5ffd5b5050505061084681612163565b6040517f5cbbd5a900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690635cbbd5a9906108b8908590600401612f81565b5f604051808303815f87803b1580156108cf575f5ffd5b505af11580156108e1573d5f5f3e3d5ffd5b505f93505050815c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169050815d505050505050565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163303610986576040517f2525631800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f02cc250d0000000000000000000000000000000000000000000000000000000081523360048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906302cc250d90602401602060405180830381865afa158015610a0e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a329190612f1f565b610a68576040517fc139eabd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff5f5c1615610aa4576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015f805c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168217905d505f610adb8484611c4d565b9050610ae6816120c9565b6040517f5cbbd5a900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690635cbbd5a990610b58908590600401612f81565b5f604051808303815f87803b158015610b6f575f5ffd5b505af1158015610b81573d5f5f3e3d5ffd5b50505050610b8e81612163565b505f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815c16815d50505050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f5f610be98433611954565b81526020019081526020015f20819055503373ffffffffffffffffffffffffffffffffffffffff167feca8ae6c58cd627e31d2272ad956830428b7087cef26fc61d7605ba56b529dcc82604051610c4291815260200190565b60405180910390a250565b5f7fffffffffffffffffffffffffffffffff000000000000000000000000000000008216610529565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163303610ce5576040517f2525631800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f02cc250d0000000000000000000000000000000000000000000000000000000081523360048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906302cc250d90602401602060405180830381865afa158015610d6d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d919190612f1f565b610dc7576040517fc139eabd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff5f5c1615610e03576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015f805c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168217905d505f610e3a8585611c4d565b9050610e45816120c9565b6040517f5cbbd5a900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690635cbbd5a990610eb7908690600401612f81565b5f604051808303815f87803b158015610ece575f5ffd5b505af1158015610ee0573d5f5f3e3d5ffd5b50505050610eed81612163565b6040517f5cbbd5a900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690635cbbd5a990610f5f908590600401612f81565b5f604051808303815f87803b158015610f76575f5ffd5b505af1158015610f88573d5f5f3e3d5ffd5b505f93505050815c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169050815d5050505050565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361102c576040517f2525631800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f02cc250d0000000000000000000000000000000000000000000000000000000081523360048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906302cc250d90602401602060405180830381865afa1580156110b4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110d89190612f1f565b61110e576040517fc139eabd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff5f5c161561114a576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015f805c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168217905d50475f8190036111b1576040517faba3a54800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8273ffffffffffffffffffffffffffffffffffffffff16826040515f6040518083038185875af1925050503d805f8114611207576040519150601f19603f3d011682016040523d82523d5f602084013e61120c565b606091505b5050905080611247576040517fd52fecf700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff167fd01205615e35ba1dd087bd6dac5922e0370961b3726c247c078cd59baae5770e8360405161128f91815260200190565b60405180910390a2505f90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815c16815d5050565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163303611334576040517f2525631800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f02cc250d0000000000000000000000000000000000000000000000000000000081523360048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906302cc250d90602401602060405180830381865afa1580156113bc573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113e09190612f1f565b611416576040517fc139eabd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff5f5c1615611452576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015f805c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168217905d505f6114898585611c4d565b6040517f5cbbd5a900000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690635cbbd5a9906114fe908690600401612f81565b5f604051808303815f87803b158015611515575f5ffd5b505af1158015611527573d5f5f3e3d5ffd5b50505050611534816120c9565b6040517f5cbbd5a900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690635cbbd5a9906115a6908590600401612f81565b5f604051808303815f87803b1580156115bd575f5ffd5b505af11580156115cf573d5f5f3e3d5ffd5b505050506115dc81612163565b505f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815c16815d5050505050565b5f60015f6116198585611954565b815260208101919091526040015f205460ff169392505050565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036116a2576040517f2525631800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f02cc250d0000000000000000000000000000000000000000000000000000000081523360048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906302cc250d90602401602060405180830381865afa15801561172a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061174e9190612f1f565b611784576040517fc139eabd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff5f5c16156117c0576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015f805c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168217905d506040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611856573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061187a9190613025565b9050805f036118b5576040517faba3a54800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118c0838383612432565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167ffff3b3844276f57024e0b42afec1a37f75db36511e43819a4f2a63ab7862b6488360405161191f91815260200190565b60405180910390a3505f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00815c16815d505050565b5f828260405160200161199692919091825260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602082015260340190565b60405160208183030381529060405280519060200120905092915050565b5f610529826119c1611ae2565b6124a2565b33301480611a0957503373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016145b15611a40576040517f4e726bd900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060015f611a4e8533611954565b815260208082019290925260409081015f2080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169315159390931790925581518481528315159181019190915233917fe5e09c712e9db70ee7241ab7dd662edc18050d7e0332cf6f2d073cd5a4f5818d910160405180910390a25050565b5f611ada848484612515565b949350505050565b5f7f00000000000000000000000000000000000000000000000000000000000000004614611c0b5750604080518082018252600681527f4f70636f6465000000000000000000000000000000000000000000000000000060209182015281518083018352600181527f31000000000000000000000000000000000000000000000000000000000000009082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527f5ada70868a718a865a2fd9ca85a7edfc69bbeff05c34eeabb718adec794eaa6b818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a0808301919091528351808303909101815260c0909101909252815191012090565b507f000000000000000000000000000000000000000000000000000000000000000090565b5f63ffffffff8216610529565b5f64010000000082161515610529565b6060818067ffffffffffffffff811115611c6957611c6961303c565b604051908082528060200260200182016040528015611ced57816020015b6040805160e0810182525f8082526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181611c875790505b509150805f03611cfd5750610529565b5f611d06611ae2565b90505f5b828110156120c05736868683818110611d2557611d25613069565b9050602002810190611d379190613096565b905080611d4760a082013561255d565b4263ffffffff60a0830135161015611d8b576040517fc56873ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608101351580611d9e57506080810135155b80611dab575060c0820135155b15611de2576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611ded82866124a2565b90505f611e0782611e026101008701876130d2565b6125b9565b90505f611e148383611954565b5f8181526020819052604090205490915064010000000060a086013516611ec7578015611e6d576040517fee3b3d4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84606001358660c0013514611eae576040517fdb46982600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f82815260208190526040902060608601359055611f3e565b846060013581101580611eea5750611ee3816060870135613160565b8660c00135115b15611f21576040517f0280215600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611f2f60c087013582613173565b5f838152602081905260409020555b611f5060c08701356080870135613186565b611f62606087013560e0890135613186565b1015611f9a576040517f74f7ce3600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040518060e001604052808581526020018473ffffffffffffffffffffffffffffffffffffffff168152602001865f016020810190611fd99190612dbc565b73ffffffffffffffffffffffffffffffffffffffff1681526020018660200160208101906120079190612dbc565b73ffffffffffffffffffffffffffffffffffffffff1681526020015f6120336060890160408a01612dbc565b73ffffffffffffffffffffffffffffffffffffffff16146120635761205e6060880160408901612dbc565b612065565b845b73ffffffffffffffffffffffffffffffffffffffff1681526020018760c0013581526020018760e001358152508a88815181106120a4576120a4613069565b6020026020010181905250505050505050806001019050611d0a565b50505092915050565b5f5b815181101561215f576121578282815181106120e9576120e9613069565b60200260200101516040015183838151811061210757612107613069565b6020026020010151602001517f000000000000000000000000000000000000000000000000000000000000000085858151811061214657612146613069565b602002602001015160a001516128bb565b6001016120cb565b5050565b5f5b815181101561215f575f82828151811061218157612181613069565b6020026020010151905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff16816060015173ffffffffffffffffffffffffffffffffffffffff16036122a357608081015160c08201516040517f068d279900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263068d2799926122719260040173ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b5f604051808303815f87803b158015612288575f5ffd5b505af115801561229a573d5f5f3e3d5ffd5b5050505061235e565b6060810151608082015160c08301516040517fa00c695100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9384166004820152918316602483015260448201527f00000000000000000000000000000000000000000000000000000000000000009091169063a00c6951906064015f604051808303815f87803b158015612347575f5ffd5b505af1158015612359573d5f5f3e3d5ffd5b505050505b806060015173ffffffffffffffffffffffffffffffffffffffff16816040015173ffffffffffffffffffffffffffffffffffffffff16826020015173ffffffffffffffffffffffffffffffffffffffff167f207bdd4bc09afcc562d729418fb78ff66daae1d18623e0f5d2ebdcb0091039718460800151855f01518660a001518760c00151604051612421949392919073ffffffffffffffffffffffffffffffffffffffff94909416845260208401929092526040830152606082015260800190565b60405180910390a450600101612165565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000080825273ffffffffffffffffffffffffffffffffffffffff8416600483015260248201839052905f8060448382895af1612492573d5f5f3e3d5ffd5b5061249c84612934565b50505050565b6040517fbe76dd4d42322ae2631eaa627d589ce5352fec12b7d61e7fc048d240a538a60d8082525f9160c085602083013760e081207f1901000000000000000000000000000000000000000000000000000000000000825284600283015280602283015250604281209250505092915050565b5f7fffffffffffffffffffffffffffffffff00000000000000000000000000000000821683612544575f61254b565b6401000000005b8563ffffffff16171790509392505050565b600161256b60216080613160565b6001901b6125799190613160565b602182901c16156125b6576040517fbb1d35e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f8181036125f3576040517f55a1e16e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f83835f81811061260657612606613069565b919091013560f81c91503690505f612621856001818961319d565b91509150825f0361263e57612637878383612a2a565b93506128b1565b826001036126a6576040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018890525f90605c0160405160208183030381529060405280519060200120905061269e818484612a2a565b9450506128b1565b826002036127e05760148110156126e9576040517f55a1e16e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b813560601c93507f1626ba7e0000000000000000000000000000000000000000000000000000000084631626ba7e89612725856014818961319d565b6040518463ffffffff1660e01b8152600401612743939291906131c4565b602060405180830381865afa15801561275e573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061278291906131dd565b7fffffffff0000000000000000000000000000000000000000000000000000000016146127db576040517fae1500ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6128b1565b8260030361287f5760148114612822576040517f55a1e16e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b813560601c935060015f6128368987611954565b815260208101919091526040015f205460ff166127db576040517f763020c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f1bc11be100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050509392505050565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000080825273ffffffffffffffffffffffffffffffffffffffff85811660048401528416602483015260448201839052905f80606483828a5af1612923573d5f5f3e3d5ffd5b5061292d85612934565b5050505050565b5f3d801561294d576020811461296c5760039150612978565b823b15600181146129615760019250612966565b600292505b50612978565b60205f5f3e5f51151591505b5080600103612985575050565b805f036129be576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806002036129f8576040517f09ee12d500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f30ae1b4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60418214612a65576040517f55a1e16e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080515f815260208082018084528790528583013560f81c92820183905285356060830181905290860135608083018190529092909160019060a0016020604051602081039080840390855afa158015612ac2573d5f5f3e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015194505073ffffffffffffffffffffffffffffffffffffffff84166128b1576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114612b5d575f5ffd5b919050565b5f5f60408385031215612b73575f5ffd5b82359150612b8360208401612b3a565b90509250929050565b5f60208284031215612b9c575f5ffd5b5035919050565b5f5f83601f840112612bb3575f5ffd5b50813567ffffffffffffffff811115612bca575f5ffd5b6020830191508360208260051b8501011115612be4575f5ffd5b9250929050565b5f60408284031215612bfb575f5ffd5b50919050565b5f5f5f5f5f60808688031215612c15575f5ffd5b853567ffffffffffffffff811115612c2b575f5ffd5b612c3788828901612ba3565b909650945050602086013567ffffffffffffffff811115612c56575f5ffd5b612c6288828901612beb565b935050604086013567ffffffffffffffff811115612c7e575f5ffd5b612c8a88828901612beb565b925050606086013567ffffffffffffffff811115612ca6575f5ffd5b612cb288828901612beb565b9150509295509295909350565b5f5f5f60408486031215612cd1575f5ffd5b833567ffffffffffffffff811115612ce7575f5ffd5b612cf386828701612ba3565b909450925050602084013567ffffffffffffffff811115612d12575f5ffd5b612d1e86828701612beb565b9150509250925092565b5f5f5f5f60608587031215612d3b575f5ffd5b843567ffffffffffffffff811115612d51575f5ffd5b612d5d87828801612ba3565b909550935050602085013567ffffffffffffffff811115612d7c575f5ffd5b612d8887828801612beb565b925050604085013567ffffffffffffffff811115612da4575f5ffd5b612db087828801612beb565b91505092959194509250565b5f60208284031215612dcc575f5ffd5b612dd582612b3a565b9392505050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b5f5f60408385031215612e40575f5ffd5b612e4983612b3a565b9150612b8360208401612b3a565b5f60c0828403128015612e68575f5ffd5b509092915050565b80151581146125b6575f5ffd5b5f5f60408385031215612e8e575f5ffd5b823591506020830135612ea081612e70565b809150509250929050565b5f5f5f60608486031215612ebd575f5ffd5b833563ffffffff81168114612ed0575f5ffd5b92506020840135612ee081612e70565b915060408401357fffffffffffffffffffffffffffffffff0000000000000000000000000000000081168114612f14575f5ffd5b809150509250925092565b5f60208284031215612f2f575f5ffd5b8151612dd581612e70565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6020815273ffffffffffffffffffffffffffffffffffffffff612fa383612b3a565b1660208201525f60208301357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612fde575f5ffd5b830160208101903567ffffffffffffffff811115612ffa575f5ffd5b803603821315613008575f5ffd5b60408085015261301c606085018284612f3a565b95945050505050565b5f60208284031215613035575f5ffd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181126130c8575f5ffd5b9190910192915050565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613105575f5ffd5b83018035915067ffffffffffffffff82111561311f575f5ffd5b602001915036819003821315612be4575f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8181038181111561052957610529613133565b8082018082111561052957610529613133565b808202811582820484141761052957610529613133565b5f5f858511156131ab575f5ffd5b838611156131b7575f5ffd5b5050820193919092039150565b838152604060208201525f61301c604083018486612f3a565b5f602082840312156131ed575f5ffd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114612dd5575f5ffdfea264697066735822122007a15f89f35a69580d13cb302aaaf07c80690aceb653a09880a9de7dc8f0d03b64736f6c634300082300336080604052348015600e575f5ffd5b50604051610ab8380380610ab8833981016040819052602b916074565b6001600160a01b038116605157604051636708512760e01b815260040160405180910390fd5b5f80546001600160a01b0319166001600160a01b0392909216919091179055609f565b5f602082840312156083575f5ffd5b81516001600160a01b03811681146098575f5ffd5b9392505050565b610a0c806100ac5f395ff3fe608060405234801561000f575f5ffd5b506004361061009f575f3560e01c8063886f039a11610072578063a00fff6f11610058578063a00fff6f14610161578063d0ebdbe714610181578063ec58f4b814610194575f5ffd5b8063886f039a1461013b5780638fd57b921461014e575f5ffd5b806302cc250d146100a3578063481c6a75146100da57806348ff15b31461011e5780637504db3e14610128575b5f5ffd5b6100c56100b136600461096e565b60026020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b5f546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100d1565b6101266101a7565b005b61012661013636600461096e565b61028c565b61012661014936600461098e565b610402565b61012661015c36600461096e565b610592565b6001546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b61012661018f36600461096e565b610655565b6101266101a236600461096e565b61071a565b60015473ffffffffffffffffffffffffffffffffffffffff1633146101f8576040517fc0fc8a8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f805460405173ffffffffffffffffffffffffffffffffffffffff93841693909116917f605c2dbf762e5f7d60a546d42e7205dcb1b011ebc62a61736a57c9089d3a435091a3600180545f80547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b5f5473ffffffffffffffffffffffffffffffffffffffff1633146102dc576040517fc0fc8a8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b475f819003610317576040517faba3a54800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8273ffffffffffffffffffffffffffffffffffffffff16826040515f6040518083038185875af1925050503d805f811461036d576040519150601f19603f3d011682016040523d82523d5f602084013e610372565b606091505b50509050806103ad576040517fd52fecf700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff167fd01205615e35ba1dd087bd6dac5922e0370961b3726c247c078cd59baae5770e836040516103f591815260200190565b60405180910390a2505050565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610452576040517fc0fc8a8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa1580156104bc573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104e091906109bf565b9050805f0361051b576040517faba3a54800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105268383836107e0565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167ffff3b3844276f57024e0b42afec1a37f75db36511e43819a4f2a63ab7862b6488360405161058591815260200190565b60405180910390a3505050565b5f5473ffffffffffffffffffffffffffffffffffffffff1633146105e2576040517fc0fc8a8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f8181526002602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f640e18a2587e1d83e4fdabf70257d0a800ca4b2c1aaad1dfc485a4ad8bbbd6c69190a250565b5f5473ffffffffffffffffffffffffffffffffffffffff1633146106a5576040517fc0fc8a8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8381169182179092555f8054604051929316917f482d6b6be65a56c613b81be64216548c489fe4a0ee64cda387ece944a9f2f82a9190a350565b5f5473ffffffffffffffffffffffffffffffffffffffff16331461076a576040517fc0fc8a8a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f8181526002602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f41f9d09dd5159251f8a8e482bbe097b7c01a5e6f70c5a0ddb494906464fc9dd79190a250565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000080825273ffffffffffffffffffffffffffffffffffffffff8416600483015260248201839052905f8060448382895af1610840573d5f5f3e3d5ffd5b5061084a84610850565b50505050565b5f3d801561086957602081146108885760039150610894565b823b156001811461087d5760019250610882565b600292505b50610894565b60205f5f3e5f51151591505b50806001036108a1575050565b805f036108da576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600203610914576040517f09ee12d500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f30ae1b4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114610969575f5ffd5b919050565b5f6020828403121561097e575f5ffd5b61098782610946565b9392505050565b5f5f6040838503121561099f575f5ffd5b6109a883610946565b91506109b660208401610946565b90509250929050565b5f602082840312156109cf575f5ffd5b505191905056fea26469706673582212203c735d823928dd64830e482839d4d809b63c229feb96d7b91e7dc040f72387a964736f6c6343000823003360a060405234801561000f575f5ffd5b506040516106c73803806106c783398101604081905261002e9161003f565b6001600160a01b031660805261006c565b5f6020828403121561004f575f5ffd5b81516001600160a01b0381168114610065575f5ffd5b9392505050565b60805161062f6100985f395f8181607e0152818161011f0152818161022901526102a4015261062f5ff3fe608060405260043610610041575f3560e01c8063068d27991461004c578063116191b61461006d5780635cbbd5a9146100c9578063a00c6951146100e8575f5ffd5b3661004857005b5f5ffd5b348015610057575f5ffd5b5061006b6100663660046104d8565b610107565b005b348015610078575f5ffd5b506100a07f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d4575f5ffd5b5061006b6100e3366004610500565b610211565b3480156100f3575f5ffd5b5061006b61010236600461053e565b61028c565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610176576040517fe7e601db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8273ffffffffffffffffffffffffffffffffffffffff16826040515f6040518083038185875af1925050503d805f81146101cc576040519150601f19603f3d011682016040523d82523d5f602084013e6101d1565b606091505b505090508061020c576040517f6d963f8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610280576040517fe7e601db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61028981610306565b50565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146102fb576040517fe7e601db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61020c83838361034a565b5f6103146020830183610578565b9050365f6103256020850185610591565b91509150604051818382375f5f8383875af4610343573d5f5f3e3d5ffd5b5050505050565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000080825273ffffffffffffffffffffffffffffffffffffffff8416600483015260248201839052905f8060448382895af16103aa573d5f5f3e3d5ffd5b506103b4846103ba565b50505050565b5f3d80156103d357602081146103f257600391506103fe565b823b15600181146103e757600192506103ec565b600292505b506103fe565b60205f5f3e5f51151591505b508060010361040b575050565b805f03610444576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060020361047e576040517f09ee12d500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f30ae1b4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b803573ffffffffffffffffffffffffffffffffffffffff811681146104d3575f5ffd5b919050565b5f5f604083850312156104e9575f5ffd5b6104f2836104b0565b946020939093013593505050565b5f60208284031215610510575f5ffd5b813567ffffffffffffffff811115610526575f5ffd5b820160408185031215610537575f5ffd5b9392505050565b5f5f5f60608486031215610550575f5ffd5b610559846104b0565b9250610567602085016104b0565b929592945050506040919091013590565b5f60208284031215610588575f5ffd5b610537826104b0565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126105c4575f5ffd5b83018035915067ffffffffffffffff8211156105de575f5ffd5b6020019150368190038213156105f2575f5ffd5b925092905056fea26469706673582212207e4c1a57aef6a1be0b5b83023c0df0af6683541b090e86560f25d32aa3365b9864736f6c6343000823003360c060405234801561000f575f5ffd5b506040516108ce3803806108ce83398101604081905261002e91610043565b6001600160a01b03166080523060a052610070565b5f60208284031215610053575f5ffd5b81516001600160a01b0381168114610069575f5ffd5b9392505050565b60805160a05161083161009d5f395f6101d601525f8181607b0152818160f1015261036301526108315ff3fe608060405234801561000f575f5ffd5b506004361061004a575f3560e01c80631171bda91461004e5780633f707e6b14610063578063c34c08e514610076578063e72c5717146100c6575b5f5ffd5b61006161005c366004610628565b6100d9565b005b610061610071366004610662565b6101bf565b61009d7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100616100d43660046106d3565b61034b565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610148576040517fc32d1d7600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101538383836104a5565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167ffff3b3844276f57024e0b42afec1a37f75db36511e43819a4f2a63ab7862b648836040516101b291815260200190565b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016300361022e576040517fe550421400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f5b81811015610345573684848381811061024c5761024c6106fb565b905060200281019061025e9190610728565b90505f8061026f6020840184610764565b73ffffffffffffffffffffffffffffffffffffffff1660208401356102976040860186610784565b6040516102a59291906107ec565b5f6040518083038185875af1925050503d805f81146102df576040519150601f19603f3d011682016040523d82523d5f602084013e6102e4565b606091505b5091509150816103375780515f0361032f576040517fd528850f0000000000000000000000000000000000000000000000000000000081526004810185905260240160405180910390fd5b805160208201fd5b505050806001019050610231565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146103ba576040517fc32d1d7600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8273ffffffffffffffffffffffffffffffffffffffff16826040515f6040518083038185875af1925050503d805f8114610410576040519150601f19603f3d011682016040523d82523d5f602084013e610415565b606091505b5050905080610450576040517fd52fecf700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff167fd01205615e35ba1dd087bd6dac5922e0370961b3726c247c078cd59baae5770e8360405161049891815260200190565b60405180910390a2505050565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000080825273ffffffffffffffffffffffffffffffffffffffff8416600483015260248201839052905f8060448382895af1610505573d5f5f3e3d5ffd5b50610345845f3d80156105235760208114610542576003915061054e565b823b1560018114610537576001925061053c565b600292505b5061054e565b60205f5f3e5f51151591505b508060010361055b575050565b805f03610594576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806002036105ce576040517f09ee12d500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f30ae1b4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114610623575f5ffd5b919050565b5f5f5f6060848603121561063a575f5ffd5b61064384610600565b925061065160208501610600565b929592945050506040919091013590565b5f5f60208385031215610673575f5ffd5b823567ffffffffffffffff811115610689575f5ffd5b8301601f81018513610699575f5ffd5b803567ffffffffffffffff8111156106af575f5ffd5b8560208260051b84010111156106c3575f5ffd5b6020919091019590945092505050565b5f5f604083850312156106e4575f5ffd5b6106ed83610600565b946020939093013593505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261075a575f5ffd5b9190910192915050565b5f60208284031215610774575f5ffd5b61077d82610600565b9392505050565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126107b7575f5ffd5b83018035915067ffffffffffffffff8211156107d1575f5ffd5b6020019150368190038213156107e5575f5ffd5b9250929050565b818382375f910190815291905056fea2646970667358221220241a9e59025df1983f5470143e28ee1ca225d0aafbe892c5b2baa6c17a2689bc64736f6c63430008230033000000000000000000000000f5512890d07a2f156d5d3481831905f30574c48f","name":"Gateway","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":false,"language":"solidity","evm_version":"cancun","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"src/Executor.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-or-later\npragma solidity 0.8.35;\n//   /$$$$$$  /$$$$$$$   /$$$$$$   /$$$$$$  /$$$$$$$  /$$$$$$$$\n//  /$$__  $$| $$__  $$ /$$__  $$ /$$__  $$| $$__  $$| $$_____/\n// | $$  \\ $$| $$  \\ $$| $$  \\__/| $$  \\ $$| $$  \\ $$| $$\n// | $$  | $$| $$$$$$$/| $$      | $$  | $$| $$  | $$| $$$$$\n// | $$  | $$| $$____/ | $$      | $$  | $$| $$  | $$| $$__/\n// | $$  | $$| $$      | $$    $$| $$  | $$| $$  | $$| $$\n// |  $$$$$$/| $$      |  $$$$$$/|  $$$$$$/| $$$$$$$/| $$$$$$$$\n//  \\______/ |__/       \\______/  \\______/ |_______/ |________/\n//\n//\n//\n\nimport {Module, ModuleLib} from \"./libraries/Module.sol\";\nimport {SafeERC20} from \"./libraries/SafeERC20.sol\";\n\n/// @title Opcode Executor (the pure dynamic `delegatecall` callee)\n/// @notice Buffer-confined routing layer, NOT a solver entry. Holds NO auth\n/// state and NOT the reentrancy lock; exposes only `runModule`/`payOut`/\n/// `payOutEth` (all `onlyGateway`). The Gateway holds the lock + user approvals\n/// and CALLs back into here; a routing module runs AS this Executor (the sole\n/// delegatecall), so its blast radius is this Executor's own buffers only.\ncontract Executor {\n    /// @dev Caller is not the Gateway contract.\n    error NotGateway();\n    /// @dev Native ETH payout to the receiver failed.\n    error EthTransferFailed();\n\n    /// @dev The Gateway: solver entry + auth/custody engine, holder of the lock\n    /// and the only allowed caller of `runModule`/`payOut`/`payOutEth`. Set\n    /// immutable (the Gateway deploys this Executor and passes itself).\n    address public immutable gateway;\n\n    constructor(address gateway_) {\n        gateway = gateway_;\n    }\n\n    /// @dev Accept ETH so a BUY_ETH buffer can be funded / WETH unwraps land here.\n    receive() external payable {}\n\n    /// @dev Restricts the entry points to the Gateway — reachable only from the\n    /// locked `Gateway.settle*`, so the Gateway-held lock covers them.\n    modifier onlyGateway() {\n        if (msg.sender != gateway) {\n            revert NotGateway();\n        }\n        _;\n    }\n\n    /// @notice Runs one routing module by `delegatecall` AS this Executor (the\n    /// sole delegatecall + sole solver-supplied code path). Gated `onlyGateway`,\n    /// called only inside the locked settle between pull and pay; reverts bubble\n    /// verbatim (atomic). A module writes only this Executor's (auth-less)\n    /// storage — it cannot forge the Gateway's auth slots or clear its lock\n    /// (different account), nor pull a user (no approval, no standalone pull).\n    function runModule(Module calldata m) external onlyGateway {\n        ModuleLib.delegate(m);\n    }\n\n    /// @notice Pays `amount` of ERC20 `token` from this Executor's inventory to\n    /// `to`. Driven by the Gateway; reverts (taking the locked settle down) if\n    /// short. `to`/`amount` come from the Gateway's signed-order memory.\n    function payOut(address token, address to, uint256 amount) external onlyGateway {\n        SafeERC20.safeTransfer(token, to, amount);\n    }\n\n    /// @notice Pays `amount` wei of this Executor's ETH buffer to `to` in a\n    /// single hop (the ETH lives here, so the Gateway need not be payable),\n    /// reverting `EthTransferFailed` on failure. Pays EXACTLY `amount` — never\n    /// drains the balance — so stray ETH is never paid out.\n    function payOutEth(address to, uint256 amount) external onlyGateway {\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool success,) = payable(to).call{value: amount}(\"\");\n        if (!success) {\n            revert EthTransferFailed();\n        }\n    }\n}\n"},{"file_path":"src/InteractionModule.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-or-later\npragma solidity 0.8.35;\n//   /$$$$$$  /$$$$$$$   /$$$$$$   /$$$$$$  /$$$$$$$  /$$$$$$$$\n//  /$$__  $$| $$__  $$ /$$__  $$ /$$__  $$| $$__  $$| $$_____/\n// | $$  \\ $$| $$  \\ $$| $$  \\__/| $$  \\ $$| $$  \\ $$| $$\n// | $$  | $$| $$$$$$$/| $$      | $$  | $$| $$  | $$| $$$$$\n// | $$  | $$| $$____/ | $$      | $$  | $$| $$  | $$| $$__/\n// | $$  | $$| $$      | $$    $$| $$  | $$| $$  | $$| $$\n// |  $$$$$$/| $$      |  $$$$$$/|  $$$$$$/| $$$$$$$/| $$$$$$$$\n//  \\______/ |__/       \\______/  \\______/ |_______/ |________/\n//\n//\n//\n\nimport {SafeERC20} from \"./libraries/SafeERC20.sol\";\n\n/// @dev A CowSwap-style `(target, value, callData)` interaction, run once via\n/// `target.call{value: value}(callData)` (CALL, not delegatecall) AS the Executor.\n/// `value` is drawn from the Executor's own balance, `callData` forwarded verbatim.\nstruct Interaction {\n    address target;\n    uint256 value;\n    bytes callData;\n}\n\n/// @title Opcode Interaction Module (default routing target)\n/// @notice Stateless generic interaction runner — the default routing module in a\n/// solver's plan, delegatecalled by `Executor.runModule` so `execute` runs AS the\n/// Executor (`address(this) == executor`). It uses CALL not delegatecall (it is\n/// itself a delegatecall TARGET, never a delegatecaller). Buffer-confined: it\n/// cannot pull a user, forge Gateway auth, or clear the lock; its blast radius is\n/// the Executor's buffers.\n///\n/// `execute` is DELEGATECALL-ONLY (a direct call reverts), so the impl contract's\n/// OWN balance can never be swept via `execute`. The ONLY way to move funds that\n/// land on the impl by accident is the Executor-gated `recover*` — so an\n/// accidental ERC20/ETH transfer is never permanently stuck, yet only the bound\n/// Executor can sweep it. `recover*` moves ONLY the impl's own balance (a direct\n/// call → `address(this)` is the impl), never the Executor's buffers or user\n/// funds; a delegatecalled `recover*` carries `msg.sender == gateway != executor`\n/// → reverts, so it can never run in the Executor's context.\ncontract InteractionModule {\n    /// @dev An interaction reverted with empty return data.\n    error InteractionFailed(uint256 index);\n    /// @dev `execute` was called directly instead of delegatecalled into a host.\n    error DirectCallForbidden();\n    /// @dev A `recover*` caller is not the bound Executor.\n    error NotExecutor();\n    /// @dev `recoverEth`'s transfer failed.\n    error EthRecoveryFailed();\n\n    /// @notice Emitted when ERC20 `token` accidentally sent to THIS impl is\n    /// recovered to `to` (Executor-gated; moves only the impl's own balance).\n    event Recovered(address indexed token, address indexed to, uint256 amount);\n    /// @notice Emitted when native ETH on THIS impl is recovered to `to`.\n    event EthRecovered(address indexed to, uint256 amount);\n\n    /// @dev The Executor this module is bound to — the ONLY address permitted to\n    /// `recover*` funds accidentally sent to THIS impl contract.\n    address public immutable executor;\n    /// @dev This impl's own deployment address; `execute` requires\n    /// `address(this) != self` (delegatecall-only).\n    address private immutable self;\n\n    constructor(address executor_) {\n        executor = executor_;\n        self = address(this);\n    }\n\n    /// @dev Restricts `recover*` to the bound Executor.\n    modifier onlyExecutor() {\n        if (msg.sender != executor) {\n            revert NotExecutor();\n        }\n        _;\n    }\n\n    /// @notice Runs `interactions` in order, each a plain CALL from the Executor's\n    /// context. DELEGATECALL-ONLY: a direct call reverts. Reverts the whole settle\n    /// on the first failure; non-empty revert data bubbles verbatim, else\n    /// [`InteractionFailed`]. Success return data is discarded.\n    function execute(Interaction[] calldata interactions) external {\n        if (address(this) == self) {\n            revert DirectCallForbidden();\n        }\n        uint256 numInteractions = interactions.length;\n        for (uint256 i; i < numInteractions; ++i) {\n            Interaction calldata interaction = interactions[i];\n\n            // solhint-disable-next-line avoid-low-level-calls\n            (bool ok, bytes memory ret) = interaction.target.call{value: interaction.value}(interaction.callData);\n\n            if (!ok) {\n                if (ret.length == 0) {\n                    revert InteractionFailed(i);\n                }\n                // solhint-disable-next-line no-inline-assembly\n                assembly (\"memory-safe\") {\n                    revert(add(ret, 0x20), mload(ret))\n                }\n            }\n        }\n    }\n\n    /// @notice Recovers ERC20 `token` accidentally sent to THIS impl contract, to\n    /// `to`. Executor-only. Moves ONLY this impl's own balance — never the\n    /// Executor's buffers or any user funds.\n    function recoverERC20(address token, address to, uint256 amount) external onlyExecutor {\n        SafeERC20.safeTransfer(token, to, amount);\n        emit Recovered(token, to, amount);\n    }\n\n    /// @notice Recovers `amount` wei of ETH (e.g. force-sent) on THIS impl\n    /// contract, to `to`. Executor-only.\n    function recoverEth(address to, uint256 amount) external onlyExecutor {\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool ok,) = to.call{value: amount}(\"\");\n        if (!ok) {\n            revert EthRecoveryFailed();\n        }\n        emit EthRecovered(to, amount);\n    }\n}\n"},{"file_path":"src/SolverList.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-or-later\npragma solidity 0.8.35;\n//   /$$$$$$  /$$$$$$$   /$$$$$$   /$$$$$$  /$$$$$$$  /$$$$$$$$\n//  /$$__  $$| $$__  $$ /$$__  $$ /$$__  $$| $$__  $$| $$_____/\n// | $$  \\ $$| $$  \\ $$| $$  \\__/| $$  \\ $$| $$  \\ $$| $$\n// | $$  | $$| $$$$$$$/| $$      | $$  | $$| $$  | $$| $$$$$\n// | $$  | $$| $$____/ | $$      | $$  | $$| $$  | $$| $$__/\n// | $$  | $$| $$      | $$    $$| $$  | $$| $$  | $$| $$\n// |  $$$$$$/| $$      |  $$$$$$/|  $$$$$$/| $$$$$$$/| $$$$$$$$\n//  \\______/ |__/       \\______/  \\______/ |_______/ |________/\n//\n//\n//\n\nimport {SafeERC20} from \"./libraries/SafeERC20.sol\";\n\n/// @dev Minimal ERC20 balance view — only `balanceOf` is read, to size the\n/// stray-fund recovery sweep of THIS contract's OWN balance.\ninterface IERC20 {\n    function balanceOf(address account) external view returns (uint256);\n}\n\n/// @title Opcode Solver Allow-List\n/// @notice Manager-curated allow-list of solver addresses permitted to call\n/// the settlement entry points. Plain immutable deployment — no proxy, no\n/// initializer, no storage reader machinery.\n///\n/// The manager role transfers by a TWO-STEP handshake (`setManager` proposes a\n/// `pendingManager`; the proposed address `acceptManager`s), so a typo'd or\n/// `address(0)` target can never brick the allow-list: the role does not move\n/// until the NEW manager proves control by accepting. The constructor likewise\n/// rejects a zero initial manager.\ncontract SolverList {\n    /// @dev Caller is not the manager.\n    error NotManager();\n    /// @dev The constructor was handed a zero initial manager — a bricked\n    /// allow-list (no address could ever mutate it) is rejected at deploy time.\n    error ZeroManager();\n    /// @dev A stray-fund recovery found a zero balance — nothing to sweep, so\n    /// the call reverts rather than emit a no-op event / 0-value transfer.\n    error NothingToRecover();\n    /// @dev `recoverEth`'s native transfer to the recipient failed.\n    error EthRecoveryFailed();\n\n    /// @dev A solver was added to the allow-list.\n    event SolverAdded(address indexed solver);\n    /// @dev A solver was removed from the allow-list.\n    event SolverRemoved(address indexed solver);\n    /// @dev The manager role was transferred (the second, completing step of the\n    /// handshake — emitted by `acceptManager`, not by `setManager`).\n    event ManagerChanged(address indexed oldManager, address indexed newManager);\n    /// @dev The first step of the manager handshake: `current` proposed\n    /// `pending` as the next manager. The role does NOT move until `pending`\n    /// calls `acceptManager`.\n    event ManagerTransferStarted(address indexed current, address indexed pending);\n    /// @dev Stray ERC20 `token` on THIS contract was swept to `to` (manager-only;\n    /// moves only this contract's OWN balance, never a third party's).\n    event Recovered(address indexed token, address indexed to, uint256 amount);\n    /// @dev Stray native ETH on THIS contract was swept to `to`.\n    event EthRecovered(address indexed to, uint256 amount);\n\n    /// @dev The address allowed to mutate the allow-list.\n    address public manager;\n\n    /// @dev The proposed next manager, set by `setManager` and consumed by\n    /// `acceptManager`. `address(0)` means no transfer is pending (and setting it\n    /// to zero cancels a pending one — harmless, since no one can accept zero).\n    address public pendingManager;\n\n    /// @dev The set of allowed solvers.\n    mapping(address => bool) public isSolver;\n\n    constructor(address initialManager) {\n        if (initialManager == address(0)) {\n            revert ZeroManager();\n        }\n        manager = initialManager;\n    }\n\n    modifier onlyManager() {\n        if (msg.sender != manager) {\n            revert NotManager();\n        }\n        _;\n    }\n\n    /// @dev Adds `solver` to the allow-list. Manager only.\n    function addSolver(address solver) external onlyManager {\n        isSolver[solver] = true;\n        emit SolverAdded(solver);\n    }\n\n    /// @dev Removes `solver` from the allow-list. Manager only.\n    function removeSolver(address solver) external onlyManager {\n        isSolver[solver] = false;\n        emit SolverRemoved(solver);\n    }\n\n    /// @dev STEP 1 of the manager handshake: proposes `newManager` as the next\n    /// manager. The role does NOT change here — it transfers only when\n    /// `newManager` calls `acceptManager`. Passing `address(0)` is allowed and\n    /// CANCELS any pending transfer (harmless: nobody can accept the zero\n    /// address). Manager only. This two-step design is what makes a typo'd /\n    /// zero target unable to brick the allow-list.\n    function setManager(address newManager) external onlyManager {\n        pendingManager = newManager;\n        emit ManagerTransferStarted(manager, newManager);\n    }\n\n    /// @dev STEP 2 of the manager handshake: the `pendingManager` claims the\n    /// role, proving it controls the new address. Reverts `NotManager` for any\n    /// other caller (so a `pendingManager` of `address(0)` is unclaimable — the\n    /// current manager keeps the role). Clears `pendingManager` on success.\n    function acceptManager() external {\n        if (msg.sender != pendingManager) {\n            revert NotManager();\n        }\n        emit ManagerChanged(manager, pendingManager);\n        manager = pendingManager;\n        pendingManager = address(0);\n    }\n\n    // ------------------------------------------------------- stray-fund recovery\n    //\n    // The allow-list holds NO funds in normal operation, so a token/ETH balance\n    // here is always accidental (a mis-sent transfer / force-fed ETH). These\n    // sweeps move ONLY this contract's OWN balance (`address(this)`) to a\n    // manager-chosen recipient — there is NO `from`/source parameter and NO\n    // `transferFrom`, so they can never touch a third party's funds. Gated to the\n    // manager (the natural privileged role on this contract).\n\n    /// @dev Sweeps THIS contract's full ERC20 `token` balance to `to`. Manager\n    /// only. Reverts `NothingToRecover` on a zero balance (no no-op transfer /\n    /// event). Moves only this contract's own (stray) balance.\n    function recoverERC20(address token, address to) external onlyManager {\n        uint256 bal = IERC20(token).balanceOf(address(this));\n        if (bal == 0) {\n            revert NothingToRecover();\n        }\n        SafeERC20.safeTransfer(token, to, bal);\n        emit Recovered(token, to, bal);\n    }\n\n    /// @dev Sweeps THIS contract's full native ETH balance to `to`. Manager only.\n    /// Reverts `NothingToRecover` on a zero balance. Recovers only force-fed /\n    /// stray ETH (this contract is non-payable, so ETH never arrives normally).\n    function recoverEth(address to) external onlyManager {\n        uint256 bal = address(this).balance;\n        if (bal == 0) {\n            revert NothingToRecover();\n        }\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool ok,) = to.call{value: bal}(\"\");\n        if (!ok) {\n            revert EthRecoveryFailed();\n        }\n        emit EthRecovered(to, bal);\n    }\n}\n"},{"file_path":"src/libraries/Module.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-or-later\npragma solidity 0.8.35;\n//   /$$$$$$  /$$$$$$$   /$$$$$$   /$$$$$$  /$$$$$$$  /$$$$$$$$\n//  /$$__  $$| $$__  $$ /$$__  $$ /$$__  $$| $$__  $$| $$_____/\n// | $$  \\ $$| $$  \\ $$| $$  \\__/| $$  \\ $$| $$  \\ $$| $$\n// | $$  | $$| $$$$$$$/| $$      | $$  | $$| $$  | $$| $$$$$\n// | $$  | $$| $$____/ | $$      | $$  | $$| $$  | $$| $$__/\n// | $$  | $$| $$      | $$    $$| $$  | $$| $$  | $$| $$\n// |  $$$$$$/| $$      |  $$$$$$/|  $$$$$$/| $$$$$$$/| $$$$$$$$\n//  \\______/ |__/       \\______/  \\______/ |_______/ |________/\n//\n//\n//\n\n/// @dev A routing module, delegatecalled IN THE EXECUTOR's context (the sole\n/// solver-supplied code path). `module` runs with `address(this) == executor`\n/// and reads/writes the EXECUTOR's storage, never the Gateway's — so it cannot\n/// forge the Gateway's auth state or clear its lock (a different account), and\n/// its identity to any contract is the Executor (trusted for nothing privileged,\n/// holds no user approval). `callData` is the ABI-encoded call it runs,\n/// interpreted entirely by `module`; the Executor forwards it verbatim.\nstruct Module {\n    address module;\n    bytes callData;\n}\n\n/// @title Opcode Routing Module Library\n/// @notice Runs a routing [`Module`] by `delegatecall` — the SOLE delegatecall\n/// in the protocol, reachable only from `Executor.runModule`. The Gateway never\n/// delegatecalls, so a module's code only ever runs in the isolated, auth-less,\n/// lock-less Executor namespace; its blast radius is the Executor's buffers.\nlibrary ModuleLib {\n    /// @dev Delegatecall `routingModule.module` with its `callData`, bubbling\n    /// revert data verbatim. No `value` (delegatecall inherits the Executor's\n    /// context); success return data is discarded.\n    function delegate(Module calldata routingModule) internal {\n        address module = routingModule.module;\n        bytes calldata callData = routingModule.callData;\n\n        // NOTE: assembly to avoid copying discarded return data and a redundant\n        // calldata memcopy; the revert path's memory clobber is memory-safe.\n        // solhint-disable-next-line no-inline-assembly\n        assembly (\"memory-safe\") {\n            let freeMemoryPointer := mload(0x40)\n            calldatacopy(freeMemoryPointer, callData.offset, callData.length)\n            if iszero(delegatecall(gas(), module, freeMemoryPointer, callData.length, 0, 0)) {\n                returndatacopy(0, 0, returndatasize())\n                revert(0, returndatasize())\n            }\n        }\n    }\n}\n"},{"file_path":"src/libraries/Order.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-or-later\npragma solidity 0.8.35;\n//   /$$$$$$  /$$$$$$$   /$$$$$$   /$$$$$$  /$$$$$$$  /$$$$$$$$\n//  /$$__  $$| $$__  $$ /$$__  $$ /$$__  $$| $$__  $$| $$_____/\n// | $$  \\ $$| $$  \\ $$| $$  \\__/| $$  \\ $$| $$  \\ $$| $$\n// | $$  | $$| $$$$$$$/| $$      | $$  | $$| $$  | $$| $$$$$\n// | $$  | $$| $$____/ | $$      | $$  | $$| $$  | $$| $$__/\n// | $$  | $$| $$      | $$    $$| $$  | $$| $$  | $$| $$\n// |  $$$$$$/| $$      |  $$$$$$/|  $$$$$$/| $$$$$$$/| $$$$$$$$\n//  \\______/ |__/       \\______/  \\______/ |_______/ |________/\n//\n//\n//\n\n/// @title Opcode Order Library\n/// @notice Order model for the Opcode protocol — exact-input sell orders only,\n/// no buy orders.\nlibrary OrderLib {\n    /// @dev The complete signed order data. `meta` packs the rest into one word:\n    ///  - bits [0..31]:    `validTo` unix timestamp (expiry)\n    ///  - bit  [32]:       `partiallyFillable` flag\n    ///  - bits [33..127]:  RESERVED — must be zero (95 bits)\n    ///  - bits [128..255]: `appDataHash` — first 16 bytes of\n    ///                     `keccak256(appDataDocument)` (see `appDataHash`)\n    ///\n    /// `appData` is an off-chain commitment bound into the EIP-712 digest (so a\n    /// signature can't be replayed against a different document) without adding a\n    /// field or changing `TYPE_HASH`; the struct stays six fields, preserving\n    /// wallet compatibility. The contract never validates it.\n    struct Order {\n        address sellToken;\n        address buyToken;\n        address receiver;\n        uint256 sellAmount;\n        uint256 buyAmount;\n        uint256 meta;\n    }\n\n    /// @dev A solver-submitted trade execution; the full order rides in calldata\n    /// (it is hashed for signature verification). Lives here, not in `Gateway`,\n    /// because that contract's `Trade` event would clash with this struct name.\n    struct Trade {\n        Order order;\n        /// @dev Executed sell amount (exact input pulled). Must equal\n        /// `order.sellAmount` for fill-or-kill orders.\n        uint256 executedSellAmount;\n        /// @dev Executed buy amount; what the receiver gets.\n        uint256 executedBuyAmount;\n        /// @dev Scheme byte + scheme payload. See `Gateway` for the schemes.\n        bytes signature;\n    }\n\n    /// @dev The `meta` field has non-zero reserved bits (bits [33..127]).\n    error ReservedMetaBits();\n\n    /// @dev EIP-712 type hash over exactly the six [`Order`] fields.\n    bytes32 internal constant TYPE_HASH = keccak256(\n        \"Order(address sellToken,address buyToken,address receiver,uint256 sellAmount,uint256 buyAmount,uint256 meta)\"\n    );\n\n    /// @dev `buyToken` marker for native-ETH payout. Buy-side only — a \"sell\" of\n    /// it fails the ERC20 contract-existence check (pulls go through approvals).\n    address internal constant BUY_ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n    /// @dev Bit position of the `partiallyFillable` flag inside `meta`.\n    uint256 private constant META_PARTIALLY_FILLABLE_BIT = 32;\n\n    /// @dev First reserved bit inside `meta`; reserved bits are [33..127].\n    uint256 private constant META_RESERVED_OFFSET = 33;\n\n    /// @dev Bit where `appDataHash` begins (high 128 bits [128..255]).\n    uint256 private constant META_APP_DATA_OFFSET = 128;\n\n    /// @dev Packs meta into one word (reserved bits zero by construction).\n    /// `appDataHash_` is `bytes16(0)` for \"no app data\".\n    function packMeta(uint32 validTo_, bool partiallyFillable_, bytes16 appDataHash_)\n        internal\n        pure\n        returns (uint256 meta)\n    {\n        meta = uint256(validTo_) | (partiallyFillable_ ? (1 << META_PARTIALLY_FILLABLE_BIT) : 0)\n            | (uint256(uint128(appDataHash_)) << META_APP_DATA_OFFSET);\n    }\n\n    /// @dev Extracts the `validTo` expiry timestamp from `meta`.\n    function validTo(uint256 meta) internal pure returns (uint256) {\n        return uint256(uint32(meta));\n    }\n\n    /// @dev Extracts the `partiallyFillable` flag from `meta`.\n    function isPartiallyFillable(uint256 meta) internal pure returns (bool) {\n        return meta & (1 << META_PARTIALLY_FILLABLE_BIT) != 0;\n    }\n\n    /// @dev Extracts the `appDataHash` commitment (high 128 bits of `meta`). It\n    /// is never read/enforced on-chain — only bound into the signed digest for\n    /// off-chain metadata, so its width is not a security parameter (funds always\n    /// move on the signed amounts + limit). `bytes16(0)` = \"no app data\".\n    function appDataHash(uint256 meta) internal pure returns (bytes16) {\n        return bytes16(uint128(meta >> META_APP_DATA_OFFSET));\n    }\n\n    /// @dev Reverts unless the reserved meta bits [33..127] are zero. The\n    /// `appDataHash` bits [128..255] are not reserved and may be nonzero.\n    function requireReservedZero(uint256 meta) internal pure {\n        // Keep only the 95 reserved bits below `appDataHash`; any set bit illegal.\n        if ((meta >> META_RESERVED_OFFSET) & ((1 << (META_APP_DATA_OFFSET - META_RESERVED_OFFSET)) - 1) != 0) {\n            revert ReservedMetaBits();\n        }\n    }\n\n    /// @dev EIP-712 signing digest `keccak256(\"\\x19\\x01\" || domainSeparator ||\n    /// structHash)`, byte-identical to `eth_signTypedData_v4`. The six\n    /// statically-sized fields are six contiguous calldata words, so the struct\n    /// hash is the type hash + 192 bytes = 224 bytes hashed from a scratch buffer.\n    function hash(Order calldata order, bytes32 domainSeparator) internal pure returns (bytes32 digest) {\n        bytes32 typeHash = TYPE_HASH;\n        // NOTE: transient scratch past the free memory pointer (memory-safe).\n        // solhint-disable-next-line no-inline-assembly\n        assembly (\"memory-safe\") {\n            let ptr := mload(0x40)\n            mstore(ptr, typeHash)\n            // `order` is the calldata offset of the (statically-sized) struct.\n            calldatacopy(add(ptr, 32), order, 192)\n            let structHash := keccak256(ptr, 224)\n\n            // digest = keccak256(\"\\x19\\x01\" || domainSeparator || structHash)\n            mstore(ptr, \"\\x19\\x01\")\n            mstore(add(ptr, 2), domainSeparator)\n            mstore(add(ptr, 34), structHash)\n            digest := keccak256(ptr, 66)\n        }\n    }\n}\n"},{"file_path":"src/libraries/SafeERC20.sol","source_code":"// SPDX-License-Identifier: LGPL-3.0-or-later\npragma solidity 0.8.35;\n//   /$$$$$$  /$$$$$$$   /$$$$$$   /$$$$$$  /$$$$$$$  /$$$$$$$$\n//  /$$__  $$| $$__  $$ /$$__  $$ /$$__  $$| $$__  $$| $$_____/\n// | $$  \\ $$| $$  \\ $$| $$  \\__/| $$  \\ $$| $$  \\ $$| $$\n// | $$  | $$| $$$$$$$/| $$      | $$  | $$| $$  | $$| $$$$$\n// | $$  | $$| $$____/ | $$      | $$  | $$| $$  | $$| $$__/\n// | $$  | $$| $$      | $$    $$| $$  | $$| $$  | $$| $$\n// |  $$$$$$/| $$      |  $$$$$$/|  $$$$$$/| $$$$$$$/| $$$$$$$$\n//  \\______/ |__/       \\______/  \\______/ |_______/ |________/\n//\n//\n//\n\n/// @dev Minimal ERC20 interface — only the compiler-derived selector source.\ninterface IERC20Transfer {\n    function transfer(address to, uint256 value) external returns (bool);\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n/// @title Opcode Safe ERC20 Transfer Library\n/// @notice Gas-efficient safe ERC20 transfers with typed failures. A reverting\n/// token call bubbles verbatim; empty return data is accepted only if the token\n/// has code (no-return tokens like USDT), else `NotAContract`; 32 bytes are read\n/// as a boolean (any non-zero = success, OZ-compatible); any other size is\n/// malformed.\nlibrary SafeERC20 {\n    /// @dev The token returned `false` from `transfer`/`transferFrom`.\n    error TransferFailed();\n    /// @dev The token call returned no data and the token address has no code.\n    error NotAContract();\n    /// @dev The token returned data that is neither empty nor a 32-byte word.\n    error MalformedTransferResult();\n\n    /// @dev `transfer` that also reverts when the token returns `false`.\n    function safeTransfer(address token, address to, uint256 value) internal {\n        bytes4 selector_ = IERC20Transfer.transfer.selector;\n\n        // solhint-disable-next-line no-inline-assembly\n        assembly (\"memory-safe\") {\n            let freeMemoryPointer := mload(0x40)\n            mstore(freeMemoryPointer, selector_)\n            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff))\n            mstore(add(freeMemoryPointer, 36), value)\n\n            if iszero(call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)) {\n                returndatacopy(0, 0, returndatasize())\n                revert(0, returndatasize())\n            }\n        }\n\n        checkLastTransferResult(token);\n    }\n\n    /// @dev `transferFrom` that also reverts when the token returns `false`.\n    function safeTransferFrom(address token, address from, address to, uint256 value) internal {\n        bytes4 selector_ = IERC20Transfer.transferFrom.selector;\n\n        // solhint-disable-next-line no-inline-assembly\n        assembly (\"memory-safe\") {\n            let freeMemoryPointer := mload(0x40)\n            mstore(freeMemoryPointer, selector_)\n            mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff))\n            mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff))\n            mstore(add(freeMemoryPointer, 68), value)\n\n            if iszero(call(gas(), token, 0, freeMemoryPointer, 100, 0, 0)) {\n                returndatacopy(0, 0, returndatasize())\n                revert(0, returndatasize())\n            }\n        }\n\n        checkLastTransferResult(token);\n    }\n\n    /// @dev Verifies the last `transfer*` return: empty (with code) or a valid\n    /// ABI boolean, else a typed revert. Must run directly after the token call —\n    /// the return data buffer is clobbered by the next external call.\n    function checkLastTransferResult(address token) private view {\n        // Outcome: 0 = returned false, 1 = success, 2 = no code, 3 = malformed.\n        uint256 outcome;\n\n        // NOTE: reading prior return data needs assembly; the 32-byte case uses\n        // reserved scratch at memory 0.\n        // solhint-disable-next-line no-inline-assembly\n        assembly (\"memory-safe\") {\n            switch returndatasize()\n            // No return: empty data from a codeless address \"succeeds\" per the\n            // Solidity calling convention, so require code.\n            case 0 {\n                switch iszero(extcodesize(token))\n                case 1 { outcome := 2 }\n                default { outcome := 1 }\n            }\n            // Boolean return: any non-zero is `true` (OZ-compatible).\n            case 32 {\n                returndatacopy(0, 0, 32)\n                outcome := iszero(iszero(mload(0)))\n            }\n            default { outcome := 3 }\n        }\n\n        if (outcome == 1) {\n            return;\n        }\n        if (outcome == 0) {\n            revert TransferFailed();\n        }\n        if (outcome == 2) {\n            revert NotAContract();\n        }\n        revert MalformedTransferResult();\n    }\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"solverManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EthRecoveryFailed","type":"error"},{"inputs":[],"name":"FillOrKillMismatch","type":"error"},{"inputs":[],"name":"ForbiddenSolver","type":"error"},{"inputs":[],"name":"InvalidEip1271Signature","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"LimitNotMet","type":"error"},{"inputs":[],"name":"MalformedSignature","type":"error"},{"inputs":[],"name":"MalformedTransferResult","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"NotPreSigned","type":"error"},{"inputs":[],"name":"NotSolver","type":"error"},{"inputs":[],"name":"NothingToRecover","type":"error"},{"inputs":[],"name":"OrderAlreadyFilled","type":"error"},{"inputs":[],"name":"OrderExpired","type":"error"},{"inputs":[],"name":"OrderOverfill","type":"error"},{"inputs":[],"name":"Reentrancy","type":"error"},{"inputs":[],"name":"ReservedMetaBits","type":"error"},{"inputs":[],"name":"SelfPreSignForbidden","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UnknownSignatureScheme","type":"error"},{"inputs":[],"name":"ZeroAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EthRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bytes32","name":"orderDigest","type":"bytes32"}],"name":"OrderInvalidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bytes32","name":"orderDigest","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"signed","type":"bool"}],"name":"PreSignatureSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"sellToken","type":"address"},{"indexed":true,"internalType":"address","name":"buyToken","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"bytes32","name":"orderDigest","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"executedSellAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"executedBuyAmount","type":"uint256"}],"name":"Trade","type":"event"},{"inputs":[],"name":"BUY_ETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_NAME","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_TYPE_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORDER_TYPE_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"executor","outputs":[{"internalType":"contract Executor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderDigest","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"}],"name":"fillKey","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderDigest","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"}],"name":"filled","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"filledAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint256","name":"meta","type":"uint256"}],"internalType":"struct OrderLib.Order","name":"order","type":"tuple"}],"name":"hashOrder","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interactionModule","outputs":[{"internalType":"contract InteractionModule","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderDigest","type":"bytes32"}],"name":"invalidateOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"meta","type":"uint256"}],"name":"metaAppDataHash","outputs":[{"internalType":"bytes16","name":"","type":"bytes16"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"meta","type":"uint256"}],"name":"metaPartiallyFillable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"meta","type":"uint256"}],"name":"metaValidTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint32","name":"validTo_","type":"uint32"},{"internalType":"bool","name":"partiallyFillable_","type":"bool"},{"internalType":"bytes16","name":"appDataHash_","type":"bytes16"}],"name":"packMeta","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"preSignatures","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderDigest","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"}],"name":"preSigned","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"recoverEth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderDigest","type":"bytes32"},{"internalType":"bool","name":"signed","type":"bool"}],"name":"setPreSignature","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint256","name":"meta","type":"uint256"}],"internalType":"struct OrderLib.Order","name":"order","type":"tuple"},{"internalType":"uint256","name":"executedSellAmount","type":"uint256"},{"internalType":"uint256","name":"executedBuyAmount","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct OrderLib.Trade[]","name":"trades","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct Module","name":"mid","type":"tuple"}],"name":"settle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint256","name":"meta","type":"uint256"}],"internalType":"struct OrderLib.Order","name":"order","type":"tuple"},{"internalType":"uint256","name":"executedSellAmount","type":"uint256"},{"internalType":"uint256","name":"executedBuyAmount","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct OrderLib.Trade[]","name":"trades","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct Module","name":"mid","type":"tuple"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct Module","name":"bot","type":"tuple"}],"name":"settleB","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint256","name":"meta","type":"uint256"}],"internalType":"struct OrderLib.Order","name":"order","type":"tuple"},{"internalType":"uint256","name":"executedSellAmount","type":"uint256"},{"internalType":"uint256","name":"executedBuyAmount","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct OrderLib.Trade[]","name":"trades","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct Module","name":"top","type":"tuple"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct Module","name":"mid","type":"tuple"}],"name":"settleT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint256","name":"meta","type":"uint256"}],"internalType":"struct OrderLib.Order","name":"order","type":"tuple"},{"internalType":"uint256","name":"executedSellAmount","type":"uint256"},{"internalType":"uint256","name":"executedBuyAmount","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct OrderLib.Trade[]","name":"trades","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct Module","name":"top","type":"tuple"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct Module","name":"mid","type":"tuple"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct Module","name":"bot","type":"tuple"}],"name":"settleTB","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"solverList","outputs":[{"internalType":"contract SolverList","name":"","type":"address"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0x000000000000000000000000f5512890d07a2f156d5d3481831905f30574c48f"}