creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error AddressInsufficientBalance(address account);\n\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedInnerCall();\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert AddressInsufficientBalance(address(this));\n        }\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            revert FailedInnerCall();\n        }\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {FailedInnerCall} error.\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert AddressInsufficientBalance(address(this));\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n     * unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {FailedInnerCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n     */\n    function _revert(bytes memory returndata) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert FailedInnerCall();\n        }\n    }\n}\n"
      },
      "contracts/accountAbstraction/compliance/AbstractValidator.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport {\n    OperatorIsNotSupported,\n    OperatorIsSuspended,\n    ProtocolIsNotSupported,\n    ProtocolIsSuspended,\n    Status\n} from \"contracts/interfaces/accountAbstraction/compliance/IWhitelistingController.sol\";\nimport {\n    PoolIsSuspended\n} from \"contracts/interfaces/accountAbstraction/interpreter/adapters/index.sol\";\nimport {\n    ILiquidityPoolsController\n} from \"contracts/interfaces/accountAbstraction/interpreter/ILiquidityPoolsController.sol\";\n\nimport {Address} from \"contracts/libraries/Address.sol\";\nimport {CalldataLibrary} from \"contracts/libraries/CalldataLibrary.sol\";\n// solhint-disable-next-line no-unused-import\nimport {Command} from \"contracts/libraries/CommandLibrary.sol\";\n\nimport {ProtocolsRepository} from \"./libraries/ProtocolsRepository.sol\";\n// solhint-disable-next-line no-unused-import\nimport {TokensRepository} from \"./libraries/TokensRepository.sol\";\n\n/* solhint-disable ordering */\nabstract contract AbstractValidator {\n    using ProtocolsRepository for address;\n    using Address for address;\n    using CalldataLibrary for bytes;\n\n    /**\n     * @dev See [status](/interfaces/accountAbstraction/compliance/IWhitelistingController.sol/enum.Status.html)\n     *  definition for validation rules.\n     */\n    enum Support {\n        Required,\n        NotRequired\n    }\n\n    /// @dev This error is unreachable if there is no bugs in LiquidityPoolsController\n    error ExpectedLPCToCheckPoolOnUndefined(bytes);\n    /// @dev This error is unreachable if there is no bugs in LiquidityPoolsController\n    error ExpectedLPCToCheckProtocolOnUndefined(string);\n\n    /// @dev This function allows us to store the name of protocol in the bytecode rather than in storage\n    function protocolName() internal pure virtual returns (string memory);\n\n    function getPoolId(\n        bytes memory encodedPool,\n        Support support\n    ) internal virtual returns (uint256 poolId) {\n        address diamond = address(this);\n        ILiquidityPoolsController controller = ILiquidityPoolsController(diamond);\n\n        poolId = controller.getPoolId(protocolName(), encodedPool);\n        (Status poolStatus, Status protocolStatus) = controller.getPoolStatus(\n            protocolName(),\n            poolId\n        );\n\n        // --- This 2 errors are unreachable if there is no bugs in LiquidityPoolsController\n        if (poolStatus == Status.Undefined) {\n            revert ExpectedLPCToCheckPoolOnUndefined(encodedPool);\n        }\n        if (protocolStatus == Status.Undefined) {\n            revert ExpectedLPCToCheckProtocolOnUndefined(protocolName());\n        }\n        // ---\n\n        if (support == Support.Required) {\n            if (poolStatus == Status.Suspended) revert PoolIsSuspended(poolId);\n            if (protocolStatus == Status.Suspended) revert ProtocolIsSuspended(protocolName());\n        }\n    }\n\n    function getOperator(Support support) internal view virtual returns (address operator) {\n        validateOperator(operator = getOperatorUnsafe(), support);\n    }\n\n    function getOperatorUnsafe() internal view virtual returns (address) {\n        return msg.data.extractLastWordAsAddress();\n    }\n\n    function validateOperator(address operator, Support support) internal view {\n        if (support == Support.Required) {\n            enforceOperatorSupported(operator);\n        } else {\n            enforceOperatorSupportedOrSuspended(operator);\n        }\n    }\n\n    /**\n     * @dev NOTE: This can't be moved to protocols repository since we use\n     * `protocolName()` which is overriden in every protocol differently.\n     */\n    function enforceOperatorSupported(address _operator) internal view {\n        enforceOperatorSupportedOrSuspended(_operator);\n        (Status operator, Status protocol) = _operator.getOperatorStatus();\n        if (protocol == Status.Suspended) revert ProtocolIsSuspended(protocolName());\n        if (operator == Status.Suspended) revert OperatorIsSuspended(_operator);\n    }\n\n    /**\n     * @dev NOTE: This can't be moved to protocols repository since we use\n     * `protocolName()` which is overriden in every protocol differently.\n     */\n    function enforceOperatorSupportedOrSuspended(address _operator) internal view {\n        (Status operator, Status protocol) = _operator.getOperatorStatus();\n        if (protocol == Status.Undefined) revert ProtocolIsNotSupported(protocolName());\n        // NOTE: the revert below is impossible because of the check above\n        if (operator == Status.Undefined) revert OperatorIsNotSupported(_operator);\n    }\n}\n/* solhint-enable ordering */\n"
      },
      "contracts/accountAbstraction/compliance/approve/ApproveValidator.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport {CommandPresets} from \"contracts/libraries/CommandLibrary.sol\";\nimport {AbstractValidator, Command, TokensRepository} from \"../AbstractValidator.sol\";\n\n/* solhint-disable comprehensive-interface, ordering */\ncontract ApproveValidator is AbstractValidator {\n    using TokensRepository for address;\n\n    function protocolName() internal pure virtual override returns (string memory) {\n        return \"approve\";\n    }\n\n    function approve(address to, uint256) external view returns (Command[] memory) {\n        address token = getOperatorUnsafe();\n        // NOTE: this is not as strict as it could be because\n        // some protocols (like CurveFi) require on their frontends\n        // to make approvals even for the withdrawals\n        token.enforceTokenSupportedOrSuspended();\n        enforceOperatorSupportedOrSuspended(to);\n        return\n            CommandPresets.approve(token, to, 0).concat(\n                Command({target: token, value: 0, payload: msg.data})\n            );\n    }\n}\n/* solhint-enable comprehensive-interface, ordering */\n"
      },
      "contracts/accountAbstraction/compliance/libraries/ProtocolsRepository.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport {\n    ProtocolIsNotSupported,\n    ProtocolIsSuspended,\n    Status\n} from \"contracts/interfaces/accountAbstraction/compliance/IWhitelistingController.sol\";\n\nlibrary StringTruncatedHash {\n    function truncatedHash(string memory _self) internal pure returns (bytes31) {\n        return bytes31(keccak256(bytes(_self)));\n    }\n}\n\nlibrary ProtocolsRepository {\n    using StringTruncatedHash for string;\n\n    struct Protocol {\n        address evaluator;\n        Status status;\n    }\n\n    struct Operator {\n        bytes31 protocolNameHash;\n        Status status;\n    }\n\n    struct Storage {\n        mapping(bytes31 protocolNameHash => Protocol) protocols;\n        mapping(address externalOperator => Operator) operators;\n    }\n\n    bytes32 private constant STORAGE_SLOT = keccak256(\"Supported Protocols repository slot V1\");\n\n    error ProtocolMustNotBeEmptyString();\n\n    /// @dev We mark protocol as memory here to make unit testing easier\n    function updateProtocolSupport(\n        string memory _protocol,\n        address _adapterEvaluator,\n        bool _supported\n    ) internal returns (bool storageModified_) {\n        if (bytes(_protocol).length == 0) revert ProtocolMustNotBeEmptyString();\n        Protocol storage prot = protocol(_protocol);\n        if (\n            _supported && (prot.status != Status.Supported || prot.evaluator != _adapterEvaluator)\n        ) {\n            prot.status = Status.Supported;\n            prot.evaluator = _adapterEvaluator;\n            storageModified_ = true;\n        } else if (!_supported && prot.status == Status.Supported) {\n            prot.status = Status.Suspended;\n            storageModified_ = true;\n        }\n    }\n\n    /// @dev We mark protocol as memory here to make unit testing easier\n    function updateOperatorSupport(\n        string memory _protocol,\n        address _source,\n        bool _supported\n    ) internal returns (bool storageModified_) {\n        if (bytes(_protocol).length == 0) revert ProtocolMustNotBeEmptyString();\n        Operator storage op = operator(_source);\n        bytes31 protHash = _protocol.truncatedHash();\n\n        if (_supported && (op.status != Status.Supported || op.protocolNameHash != protHash)) {\n            op.protocolNameHash = protHash;\n            op.status = Status.Supported;\n            storageModified_ = true;\n        } else if (!_supported && op.status == Status.Supported) {\n            op.status = Status.Suspended;\n            storageModified_ = true;\n        }\n    }\n\n    function enforceProtocolSupported(string calldata _protocol) internal view {\n        Status status = getProtocolStatus(_protocol);\n        if (status != Status.Supported) {\n            if (status == Status.Suspended) revert ProtocolIsSuspended(_protocol);\n            else revert ProtocolIsNotSupported(_protocol);\n        }\n    }\n\n    function enforceProtocolSupportedOrSuspended(string calldata _protocol) internal view {\n        Status status = getProtocolStatus(_protocol);\n        if (status == Status.Undefined) revert ProtocolIsNotSupported(_protocol);\n    }\n\n    function getProtocolStatus(string calldata _protocol) internal view returns (Status) {\n        return protocol(_protocol).status;\n    }\n\n    function getProtocolEvaluator(string calldata _protocol) internal view returns (address) {\n        return protocol(_protocol).evaluator;\n    }\n\n    function getOperatorStatus(\n        address _source\n    ) internal view returns (Status operator_, Status protocol_) {\n        operator_ = operator(_source).status;\n        protocol_ = _storage().protocols[operator(_source).protocolNameHash].status;\n    }\n\n    function protocol(string memory _name) private view returns (Protocol storage) {\n        return _storage().protocols[_name.truncatedHash()];\n    }\n\n    function operator(address _source) private view returns (Operator storage) {\n        return _storage().operators[_source];\n    }\n\n    function _storage() private pure returns (Storage storage) {\n        bytes32 storageSlot = STORAGE_SLOT;\n        Storage storage state;\n        assembly {\n            state.slot := storageSlot\n        }\n        return state;\n    }\n}\n"
      },
      "contracts/accountAbstraction/compliance/libraries/TokensRepository.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport {\n    Status,\n    TokenIsNotSupported,\n    TokenIsSuspended,\n    TokenLevelInsufficient,\n    TokenPermission\n} from \"contracts/interfaces/accountAbstraction/compliance/IWhitelistingController.sol\";\n\nlibrary TokensRepository {\n    struct Token {\n        Status status;\n        TokenPermission perm;\n    }\n\n    struct Storage {\n        mapping(address source => Token) tokens;\n    }\n\n    bytes32 private constant STORAGE_SLOT = keccak256(\"Supported Tokens repository slot V1\");\n\n    error CannotRecognizeTokenPermission(TokenPermission);\n    /// @dev We can suspend token, but it's permission will never fall\n    /// to None. None reserved for undefined case just because it would\n    /// be strange to return TradeOnly permission for undefined tokens.\n    error CannotSetPermissionToNone(address);\n\n    function updateTokenSupport(\n        address token,\n        bool supported,\n        TokenPermission perm\n    ) internal returns (bool storageModified) {\n        bool s = updateTokenStatus(token, supported);\n        bool p = updateTokenPerm(token, perm);\n        storageModified = s || p;\n    }\n\n    function enforceTokenSupported(address token) internal view {\n        Status status = getTokenStatus(token);\n        if (status != Status.Supported) {\n            if (status == Status.Suspended) revert TokenIsSuspended(token);\n            else revert TokenIsNotSupported(token);\n        }\n    }\n\n    function enforceTokenSupportedOrSuspended(address token) internal view {\n        Status status = getTokenStatus(token);\n        if (status == Status.Undefined) revert TokenIsNotSupported(token);\n    }\n\n    function enforceTokenHasPermission(address token, TokenPermission required) internal view {\n        TokenPermission current = getTokenPerm(token);\n        if (current == required) return;\n        // if not matched then we check levels\n        if (getPermLevel(current) > getPermLevel(required)) return;\n        // at this point we know that niether permissions matched\n        // nor the current one is higher than required, so\n        // it's either current is lower than the required (bad)\n        // or equal to it which is only possible for level 2\n        // which is not compatible (Collateral != Leverage)\n        revert TokenLevelInsufficient(token, required, current);\n    }\n\n    function getTokenStatus(address token) internal view returns (Status) {\n        return _storage()[token].status;\n    }\n\n    function getTokenPerm(address token) internal view returns (TokenPermission) {\n        return _storage()[token].perm;\n    }\n\n    function updateTokenStatus(\n        address token,\n        bool supported\n    ) private returns (bool storageModified) {\n        Status current = getTokenStatus(token);\n        if (supported && current != Status.Supported) {\n            _storage()[token].status = Status.Supported;\n            storageModified = true;\n        } else if (!supported && current == Status.Supported) {\n            _storage()[token].status = Status.Suspended;\n            storageModified = true;\n        }\n    }\n\n    function updateTokenPerm(\n        address token,\n        TokenPermission perm\n    ) private returns (bool storageModified) {\n        if (perm == TokenPermission.None) revert CannotSetPermissionToNone(token);\n\n        if (getTokenPerm(token) != perm) {\n            _storage()[token].perm = perm;\n            storageModified = true;\n        }\n    }\n\n    function _storage() private view returns (mapping(address => Token) storage) {\n        bytes32 storageSlot = STORAGE_SLOT;\n        Storage storage state;\n        assembly {\n            state.slot := storageSlot\n        }\n        return state.tokens;\n    }\n\n    function getPermLevel(TokenPermission perm) private pure returns (uint256) {\n        if (perm == TokenPermission.None) return 0;\n        if (perm == TokenPermission.TradeOnly) return 1;\n        if (perm == TokenPermission.Collateral) return 2;\n        if (perm == TokenPermission.Leverage) return 2;\n        if (perm == TokenPermission.FullAccess) return 3;\n        revert CannotRecognizeTokenPermission(perm);\n    }\n}\n"
      },
      "contracts/interfaces/accountAbstraction/compliance/Asset.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport {AssetLibrary} from \"contracts/libraries/AssetLibrary.sol\";\n\n/**\n * @title Asset\n * @dev Represents an asset with its token address and the amount.\n * @param token The address of the asset's token.\n * @param amount The amount of the asset.\n */\nstruct Asset {\n    address token;\n    uint256 amount;\n}\n\nusing AssetLibrary for Asset global;\n"
      },
      "contracts/interfaces/accountAbstraction/compliance/IWhitelistingController.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\n/**\n * @title Status\n * @notice Enum representing status of a record (e.g., token, protocol, operator)\n *  used for operation validation.\n * @notice Validators must adhere to the following rules for different operations and contexts:\n *  1) For exchanges: `operator`, `pool`, and `input token` *MAY* be either supported or suspended, but the `output token` *MUST* be supported.\n *  2) For deposits: `operator`, `pool`, and every `token` in the `pool` *MUST* be supported.\n *  3) For withdrawals: `operator`, `pool`, and each `token` *MAY* be either supported or suspended.\n *\n * @dev **Note** that deposit denotes **all** ways of aquiring liquidity such\n * as token deposit, LP tokens stake, NFT mint etc.\n */\nenum Status {\n    Undefined,\n    Supported,\n    Suspended\n}\n\n/**\n * @title WhitelistingAddressRecord\n * @notice A struct to store an address and its support status.\n * @dev This struct stores an address and its support status.\n * @dev `source`: The address to be stored.\n * @dev `supported`: Indicates whether the address is supported or not.\n */\nstruct WhitelistingAddressRecord {\n    address source;\n    bool supported;\n}\n\n/**\n * @title TokenPermission\n * @notice This enum represents different levels of permission for a token, including trading, collateral, leverage, and full access.\n * @dev `None`: Represents no permissions granted for the token.\n * @dev `TradeOnly`: Represents the lowest permission level where you can only trade the token.\n * @dev `Collateral`: Allows you to use the token as collateral.\n * @dev `Leverage`: Allows you to leverage the token.\n * @dev `FullAccess`: Represents the highest permission level where you have full access to trade, use as collateral, and leverage the token.\n */\nenum TokenPermission {\n    None,\n    TradeOnly,\n    Collateral,\n    Leverage,\n    FullAccess\n}\n\n/**\n * @title WhitelistingTokenRecord\n * @notice This struct stores an address and its support status for whitelisting, collateral and leverage.\n * @dev `source`: The address of the token.\n * @dev `supported`: Whether the token can be received from a protocol trades.\n * @dev `permission`: Level of [`TokenPermission`](./enum.TokenPermission.html).\n */\nstruct WhitelistingTokenRecord {\n    address source;\n    bool supported;\n    TokenPermission permission;\n}\n\n/**\n * @notice An error indicating that a token is not supported by the whitelisting controller.\n * @dev This error is thrown when an unsupported token is used.\n * @dev `token`: The address of the unsupported token.\n */\nerror TokenIsNotSupported(address token);\n\n/**\n * @notice An error indicating that a token is suspended by the whitelisting controller.\n * @dev This error is thrown when a suspended token is used.\n * @dev `token`: The address of the suspended token.\n */\nerror TokenIsSuspended(address token);\n\n/**\n * @notice An error indicating that the token's permission level is insufficient for the requested action.\n * @dev This can be thrown at [`IWhitelistingController.enforceTokenHasPermission()`](./interface.IWhitelistingController.html#enforcetokenhaspermission)\n * @param token The address of the token that has insufficient permissions.\n * @param required The required permission level for the action.\n * @param actual The actual permission level of the token.\n */\nerror TokenLevelInsufficient(address token, TokenPermission required, TokenPermission actual);\n\n/**\n * @notice An error indicating that an operator is not supported by the whitelisting controller.\n * @dev This error is thrown when an unsupported operator is used.\n * @dev `operator`: The address of the unsupported operator.\n */\nerror OperatorIsNotSupported(address operator);\n\n/**\n * @notice An error indicating that an operator is suspended by the whitelisting controller.\n * @dev This error is thrown when a suspended operator is used.\n * @dev `operator`: The address of the suspended operator.\n */\nerror OperatorIsSuspended(address operator);\n\n/**\n * @notice An error indicating that a protocol is not supported by the whitelisting controller.\n * @dev This error is thrown when an unsupported protocol is used.\n * @dev `protocol`: The identification string of the unsupported protocol.\n */\nerror ProtocolIsNotSupported(string protocol);\n\n/**\n * @notice An error indicating that a protocol is suspended by the whitelisting controller.\n * @dev This error is thrown when a suspended protocol is used.\n * @dev `protocol`: The identification string of the unsupported protocol.\n */\nerror ProtocolIsSuspended(string protocol);\n\n/**\n * @title IWhitelistingController\n * @notice Interface for managing whitelisting of tokens, protocols, and operators.\n */\ninterface IWhitelistingController {\n    /**\n     * @dev Emitted when the support status of a protocol changes.\n     * @dev `protocol`: The identification string of the protocol.\n     * @dev `supported`: Whether the protocol is supported or not.\n     */\n    event ProtocolSupportChanged(string indexed protocol, bool supported);\n\n    /**\n     * @dev Emitted when the support status of a token changes.\n     * @dev `token`: The address of the token.\n     * @dev `supported`: Whether the token is supported or not.\n     * @dev `permission`: Level of [`TokenPermission`](./enum.TokenPermission.html).\n     */\n    event TokenSupportChanged(address indexed token, bool supported, TokenPermission permission);\n\n    /**\n     * @dev Emitted when the support status of an operator changes for a specific protocol.\n     * @dev `protocol`: The identification string of the protocol.\n     * @dev `operator`: The address of the operator.\n     * @dev `supported`: Whether the operator is supported or not.\n     */\n    event OperatorSupportChanged(string indexed protocol, address indexed operator, bool supported);\n\n    /**\n     * @notice Update the support status of multiple tokens.\n     * @dev Emits a [`TokenSupportChanged()`](#tokensupportchanged) event for each token whose status changed.\n     * @dev Reverts with an [`AlreadyUpToDate()`](/interfaces/base/CommonErrors.sol/error.AlreadyUpToDate.html)\n     *  error if no token status changed.\n     * @param _tokens An array of [`WhitelistingTokenRecord`](./struct.WhitelistingTokenRecord.html)\n     * structs containing token addresses, support statuses and permissions.\n     */\n    function updateTokensSupport(WhitelistingTokenRecord[] calldata _tokens) external;\n\n    /**\n     * @notice Update the support status of a protocol.\n     * @dev Emits a [`ProtocolSupportChanged()`](#protocolsupportchanged) event.\n     * @dev Reverts with an [`AlreadyUpToDate()`](/interfaces/base/CommonErrors.sol/error.AlreadyUpToDate.html)\n     *  error if protocol status is up to date.\n     * @param _protocol The identification string of the protocol.\n     * @param _adapterEvaluator The address of the adapter evaluator for the protocol.\n     * @param _supported Whether the protocol is supported or not.\n     */\n    function updateProtocolSupport(\n        string calldata _protocol,\n        address _adapterEvaluator,\n        bool _supported\n    ) external;\n\n    /**\n     * @notice Update the support status of multiple operators for a specific protocol.\n     * @dev Emits a [`OperatorSupportChanged()`](#operatorsupportchanged) event for each token whose status changed.\n     * @dev Reverts with an [`AlreadyUpToDate()`](/interfaces/base/CommonErrors.sol/error.AlreadyUpToDate.html)\n     *  error if no operator status changed.\n     * @param _protocol The identification string of the protocol.\n     * @param _operators An array of `WhitelistingAddressRecord` structs containing operator addresses and support statuses.\n     */\n    function updateOperatorsSupport(\n        string calldata _protocol,\n        WhitelistingAddressRecord[] calldata _operators\n    ) external;\n\n    /**\n     * @notice Ensures that a token has the specified permission level.\n     * @dev This check does not enforce exact match, but only that level is sufficient.\n     *  So if `permission` is TokenPermission.TradeOnly and the token has TokenPermission.Collateral\n     *  then it assumes that level is sufficient since Collateral level includes both\n     *  TradeOnly and Collateral levels.\n     * @param token The address of the token to check for permission.\n     * @param permission The required [`TokenPermission`](TokenPermission) to be enforced.\n     */\n    function enforceTokenHasPermission(address token, TokenPermission permission) external view;\n\n    /**\n     * @notice Returns the support status of a token as well as it's permissions.\n     * @param _token The address of the token.\n     * @return The [`Status`](./enum.Status.html)\n     * of the token.\n     * @return The [`TokenPermission`](./enum.TokenPermission.html)\n     * of the token.\n     */\n    function getTokenSupport(address _token) external view returns (Status, TokenPermission);\n\n    /**\n     * @notice Returns the support status of a protocol.\n     * @param _protocol The identification string of the protocol.\n     * @return The [`Status`](./enum.Status.html)\n     *  of the protocol.\n     */\n    function getProtocolStatus(string calldata _protocol) external view returns (Status);\n\n    /**\n     * @notice Returns the address of the adapter evaluator for a protocol.\n     * @param _protocol The identification string of the protocol.\n     * @return The address of the adapter evaluator for the protocol.\n     */\n    function getProtocolEvaluator(string calldata _protocol) external view returns (address);\n\n    /**\n     * @notice Returns the support status of an operator for a specific protocol.\n     * @param _operator The address of the operator.\n     * @return operatorStatus_ The [`Status`](./enum.Status.html)\n     *  of the operator.\n     * @return protocolStatus_ The [`Status`](./enum.Status.html)\n     *  of the protocol.\n     */\n    function getOperatorStatus(\n        address _operator\n    ) external view returns (Status operatorStatus_, Status protocolStatus_);\n}\n"
      },
      "contracts/interfaces/accountAbstraction/interpreter/adapters/IDecreasePositionEvaluator.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport {Asset} from \"contracts/libraries/AssetLibrary.sol\";\nimport {Command} from \"../Command.sol\";\nimport {PositionDescriptor} from \"./PositionDescriptor.sol\";\n\ninterface IDecreasePositionEvaluator {\n    /**\n     * @notice Request structure for decreasing a position.\n     * @dev `descriptor`: The [`PositionDescriptor`](/interfaces/accountAbstraction/interpreter/adapters/PositionDescriptor.sol/struct.PositionDescriptor.html)\n     *  struct.\n     * @dev `liquidity`: Abstract amount that can be interpreted differently in different protocols (e.g., amount of LP tokens to burn).\n     * @dev `minOutput`: [`Asset`](/interfaces/accountAbstraction/compliance/Asset.sol/struct.Asset.html) array with minimum amounts that must be retrieved from the position.\n     */\n    struct DecreasePositionRequest {\n        PositionDescriptor descriptor;\n        uint256 liquidity;\n        Asset[] minOutput;\n    }\n\n    /**\n     * @notice Evaluate a decrease position request.\n     * @param _operator Address which initiated the request\n     * @param _request The [`DecreasePositionRequest`](#decreasepositionrequest) struct containing decrease position details.\n     * @return cmds_ An array of [`Command`](../../Command.sol/struct.Command.html) to execute the request.\n     */\n    function evaluate(\n        address _operator,\n        DecreasePositionRequest calldata _request\n    ) external returns (Command[] memory cmds_);\n}\n"
      },
      "contracts/interfaces/accountAbstraction/interpreter/adapters/IExchangeEvaluator.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport {Command} from \"../Command.sol\";\n\n/**\n * @title IExchangeEvaluator\n * @notice Interface for compiling commands for token exchanges for different protocols.\n */\ninterface IExchangeEvaluator {\n    /**\n     * @notice Structure for an exchange token request.\n     * @dev `path`: Encoded path of tokens to follow in the exchange, including pool identifiers.\n     * 20 bytes(tokenA) + 4 byte(poolId_A_B) + 20 bytes(tokenB) + ...\n     * ... + 4 byte(poolId_N-1_N) + 20 bytes(tokenN).\n     * @dev `extraData`: Additional data specific to a particular protocol, such as the response from a 1Inch Exchange API.\n     * @dev `amountIn`: The amount of tokenA to spend.\n     * @dev `minAmountOut`: The minimum amount of tokenN to receive.\n     * @dev `recipient`: The recipient of tokenN.\n     */\n    struct ExchangeRequest {\n        bytes path;\n        bytes extraData;\n        uint256 amountIn;\n        uint256 minAmountOut;\n        address recipient;\n    }\n\n    /**\n     * @notice Constructs an exchange token request.\n     * @param _operator Address which initiated the request\n     * @param _request The [`ExchangeRequest`](#exchangerequest) struct containing exchange token details.\n     * @return cmds_ An array of [`Command`](../../Command.sol/struct.Command.html) to execute the request.\n     */\n    function evaluate(\n        address _operator,\n        ExchangeRequest calldata _request\n    ) external view returns (Command[] memory cmds_);\n}\n"
      },
      "contracts/interfaces/accountAbstraction/interpreter/adapters/IIncreasePositionEvaluator.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport {Asset} from \"contracts/libraries/AssetLibrary.sol\";\nimport {Command} from \"../Command.sol\";\nimport {PositionDescriptor} from \"./PositionDescriptor.sol\";\n\ninterface IIncreasePositionEvaluator {\n    /**\n     * @notice Structure for an increase position request.\n     * @dev `descriptor`: The [`PositionDescriptor`](/interfaces/accountAbstraction/interpreter/adapters/PositionDescriptor.sol/struct.PositionDescriptor.html)\n     *  struct.\n     * @dev `input`: An array of [`Asset`](/interfaces/accountAbstraction/compliance/Asset.sol/struct.Asset.html) representing the token-amounts that will be added to the position.\n     * @dev `minLiquidityOut`: An abstract amount that can be interpreted differently in different protocols (e.g., minimum amount of LP tokens to receive).\n     */\n    struct IncreasePositionRequest {\n        PositionDescriptor descriptor;\n        Asset[] input;\n        uint256 minLiquidityOut;\n    }\n\n    /**\n     * @notice Evaluate a increase position request.\n     * @param _operator Address which initiated the request\n     * @param _request The [`IncreasePositionRequest`](#increasepositionrequest) struct containing increase position details.\n     * @return cmds_ An array of [`Command`](../../Command.sol/struct.Command.html) to execute the request.\n     */\n    function evaluate(\n        address _operator,\n        IncreasePositionRequest calldata _request\n    ) external returns (Command[] memory cmds_);\n}\n"
      },
      "contracts/interfaces/accountAbstraction/interpreter/adapters/ILiquidityPoolsRepository.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\n/* solhint-disable no-unused-import */\nimport {\n    Status,\n    TokenIsNotSupported\n} from \"contracts/interfaces/accountAbstraction/compliance/IWhitelistingController.sol\";\nimport {AlreadyUpToDate} from \"contracts/interfaces/base/CommonErrors.sol\";\n/* solhint-enable no-unused-import */\n\n/**\n * @notice Error indicating that the pool ID was not found.\n * @param encodedPool The encoded pool data that was searched for.\n */\nerror PoolIdNotFound(bytes encodedPool);\n\n/**\n * @notice Error indicating that the pool does not exist.\n * @param poolId The unique identifier of the pool that was searched for.\n */\nerror PoolIsNotSupported(uint256 poolId);\n\n/**\n * @notice Error indicating that the pool is suspended.\n * @param poolId The unique identifier of the pool that is suspended.\n */\nerror PoolIsSuspended(uint256 poolId);\n\n/**\n * @title ILiquidityPoolsRepository\n * @notice Interface for managing liquidity pools and their support status.\n */\ninterface ILiquidityPoolsRepository {\n    /**\n     * @notice Update the support status of a liquidity pool.\n     * @param _encodedPool The encoded pool data.\n     * @param _supported Whether the pool is supported or not.\n     * @return poolId_ The unique identifier of the pool.\n     * @dev Reverts with a [`PoolIdNotFound()`](/interfaces/accountAbstraction/interpreter/adapters/ILiquidityPoolsRepository.sol/error.PoolIdNotFound.html)\n     *  error if the pool does not exist.\n     */\n    function updatePoolSupport(\n        bytes calldata _encodedPool,\n        bool _supported\n    ) external returns (uint256 poolId_);\n\n    /**\n     * @notice Get the status of a specific pool.\n     * @param _poolId The unique identifier of the pool.\n     * @return status The status of the pool.\n     * @dev Reverts with a [`PoolIsNotSupported()`](/interfaces/accountAbstraction/interpreter/adapters/ILiquidityPoolsRepository.sol/error.PoolIsNotSupported.html)\n     *  error if the pool does not exist.\n     */\n    function getPoolStatus(uint256 _poolId) external returns (Status status);\n\n    /**\n     * @notice Get the unique identifier (pool ID) of a specific pool.\n     * @param _encodedPool The encoded pool data.\n     * @return poolId_ The unique identifier of the pool.\n     * @dev Reverts with a [`PoolIsNotSupported()`](/interfaces/accountAbstraction/interpreter/adapters/ILiquidityPoolsRepository.sol/error.PoolIsNotSupported.html)\n     *  error if the pool does not exist.\n     */\n    function getPoolId(bytes calldata _encodedPool) external view returns (uint256 poolId_);\n}\n"
      },
      "contracts/interfaces/accountAbstraction/interpreter/adapters/index.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport {\n    IDecreasePositionEvaluator\n} from \"contracts/interfaces/accountAbstraction/interpreter/adapters/IDecreasePositionEvaluator.sol\";\nimport {\n    IExchangeEvaluator\n} from \"contracts/interfaces/accountAbstraction/interpreter/adapters/IExchangeEvaluator.sol\";\nimport {\n    IIncreasePositionEvaluator\n} from \"contracts/interfaces/accountAbstraction/interpreter/adapters/IIncreasePositionEvaluator.sol\";\nimport {\n    AlreadyUpToDate,\n    ILiquidityPoolsRepository,\n    PoolIdNotFound,\n    PoolIsNotSupported,\n    PoolIsSuspended,\n    Status,\n    TokenIsNotSupported\n} from \"contracts/interfaces/accountAbstraction/interpreter/adapters/ILiquidityPoolsRepository.sol\";\nimport {\n    PositionDescriptor\n} from \"contracts/interfaces/accountAbstraction/interpreter/adapters/PositionDescriptor.sol\";\n"
      },
      "contracts/interfaces/accountAbstraction/interpreter/adapters/PositionDescriptor.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\n// TODO CRYPTO-145: Possibly move into appropriate interface?\n/**\n * @notice Used to determine the required position for an operation.\n * @dev `poolId`: An identifier that is unique within a single protocol.\n * @dev `extraData`: Additional data used to specify the position, for example\n * this is used in OneInchV5Evaluator to pass swap tx generated via 1inch API.\n */\nstruct PositionDescriptor {\n    uint256 poolId;\n    bytes extraData;\n}\n"
      },
      "contracts/interfaces/accountAbstraction/interpreter/Command.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport {CommandLibrary} from \"contracts/libraries/CommandLibrary.sol\";\n\n/**\n * @title Command\n * @notice Contains arguments for a low-level call.\n * @dev This struct allows deferring the call's execution, suspending it by passing it to another function or contract.\n * @dev `target` The address to be called.\n * @dev `value` Value to send in the call.\n * @dev `payload` Encoded call with function selector and arguments.\n */\nstruct Command {\n    address target;\n    uint256 value;\n    bytes payload;\n}\n\nusing CommandLibrary for Command global;\n"
      },
      "contracts/interfaces/accountAbstraction/interpreter/ILiquidityPoolsController.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport {Status} from \"../compliance/IWhitelistingController.sol\";\n\n/**\n * @title WhitelistingBytesRecord\n * @notice A struct used to store encoded pool data and its support status.\n * @dev This struct is employed in the [`ILiquidityPoolsController`](/interfaces/accountAbstraction/interpreter/ILiquidityPoolsController.sol/interface.ILiquidityPoolsController.html) interface.\n * @dev `encoded`: Encoded pool data. The encoding depends on the underlying protocol.\n * For example UniswapV3 protocol expects this as `(address token0, address token1, uint24 fee)`.\n * To find out which encoding does `ProtocolName` expects,\n * check `{ProtocolName}LiquidityPoolsRepository.initializePool()`\n * @dev `supported`: Indicates whether the pool is supported.\n */\nstruct WhitelistingBytesRecord {\n    bytes encoded;\n    bool supported;\n}\n\n/**\n * @title ILiquidityPoolsController\n * @notice Interface for managing liquidity pools and their support status for different protocols.\n */\ninterface ILiquidityPoolsController {\n    /**\n     * @dev Emitted when the support status of a pool changes.\n     * @param protocol The `protocol` identifier.\n     * @param encodedPool The encoded pool data.\n     * @param poolId The unique identifier of the pool.\n     * @param supported Whether the pool is supported or not.\n     */\n    event PoolSupportChanged(\n        string indexed protocol,\n        bytes indexed encodedPool,\n        uint256 indexed poolId,\n        bool supported\n    );\n\n    /**\n     * @notice Update the support status of multiple liquidity pools for a specific protocol.\n     * @dev Reverts with an [`AlreadyUpToDate`](/interfaces/base/CommonErrors.sol/error.AlreadyUpToDate.html) error if status didn't change for any given pool.\n     * @dev Emits a [`PoolSupportChanged`](#poolsupportchanged) event for each pool.\n     * @param _protocol The `protocol` identifier.\n     * @param _pools An array of [`WhitelistingBytesRecord`](/interfaces/accountAbstraction/interpreter/ILiquidityPoolsController.sol/struct.WhitelistingBytesRecord.html#whitelistingbytesrecord) structs containing pool data and support status.\n     */\n    function updatePoolsSupport(\n        string calldata _protocol,\n        WhitelistingBytesRecord[] calldata _pools\n    ) external;\n\n    /**\n     * @notice Get the status of a specific pool and its associated protocol.\n     * @param _protocol The `protocol` identifier.\n     * @param _poolId The unique identifier of the pool.\n     * @return poolStatus_ The [`Status`](/interfaces/accountAbstraction/compliance/IWhitelistingController.sol/enum.Status.html)\n     *  of the pool.\n     * @return protocolStatus_ The [`Status`](/interfaces/accountAbstraction/compliance/IWhitelistingController.sol/enum.Status.html)\n     *  of the protocol.\n     */\n    function getPoolStatus(\n        string calldata _protocol,\n        uint256 _poolId\n    ) external returns (Status poolStatus_, Status protocolStatus_);\n\n    /**\n     * @notice Get the unique identifier (pool ID) of a specific pool.\n     * @param _protocol The `protocol` identifier.\n     * @param _encodedPool The encoded pool data. The encoding depends on the underlying protocol.\n     * For example UniswapV3 protocol expects this as (address token0, address token1, uint24 fee).\n     * To find out which encoding does `ProtocolName` expects,\n     * check {ProtocolName}LiquidityPoolsRepository.getPoolIdFromTokens()\n     * @dev `supported`: Indicates whether the pool is supported.\n\n     * @return poolId_ The unique identifier of the pool.\n     */\n    function getPoolId(\n        string calldata _protocol,\n        bytes calldata _encodedPool\n    ) external returns (uint256 poolId_);\n}\n"
      },
      "contracts/interfaces/base/CommonErrors.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\n/**\n * @notice An error indicating that the amount for the specified token is zero.\n * @param token The address of the token with a zero amount.\n */\nerror AmountMustNotBeZero(address token);\n\n/**\n * @notice An error indicating that an address must not be zero.\n */\nerror AddressMustNotBeZero();\n\n/**\n * @notice An error indicating that an array must not be empty.\n */\nerror ArrayMustNotBeEmpty();\n\n/**\n * @notice An error indicating storage is already up to date and doesn't need further processing.\n * @dev This error is thrown when attempting to update an entity(s) that is(are) already up to date.\n */\nerror AlreadyUpToDate();\n\n/**\n * @notice An error indicating that an action is unauthorized for the specified account.\n * @param account The address of the unauthorized account.\n */\nerror UnauthorizedAccount(address account);\n"
      },
      "contracts/libraries/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nlibrary Address {\n    address internal constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n    function set(bytes32 _slot, address _value) internal {\n        assembly {\n            sstore(_slot, _value)\n        }\n    }\n\n    function get(bytes32 _slot) internal view returns (address result_) {\n        assembly {\n            result_ := sload(_slot)\n        }\n    }\n\n    function isEth(address _token) internal pure returns (bool) {\n        return _token == ETH || _token == address(0);\n    }\n\n    function sort(address _a, address _b) internal pure returns (address, address) {\n        return _a < _b ? (_a, _b) : (_b, _a);\n    }\n\n    function sort(address[4] memory _array) internal pure returns (address[4] memory _sorted) {\n        // Sorting network for the array of length 4\n        (_sorted[0], _sorted[1]) = sort(_array[0], _array[1]);\n        (_sorted[2], _sorted[3]) = sort(_array[2], _array[3]);\n\n        (_sorted[0], _sorted[2]) = sort(_sorted[0], _sorted[2]);\n        (_sorted[1], _sorted[3]) = sort(_sorted[1], _sorted[3]);\n        (_sorted[1], _sorted[2]) = sort(_sorted[1], _sorted[2]);\n    }\n}\n"
      },
      "contracts/libraries/AssetLibrary.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport {SafeTransferLib} from \"solady/src/utils/SafeTransferLib.sol\";\n\nimport {Asset} from \"contracts/interfaces/accountAbstraction/compliance/Asset.sol\";\nimport {AmountMustNotBeZero} from \"contracts/interfaces/base/CommonErrors.sol\";\n\nimport {Address} from \"./Address.sol\";\n\nlibrary AssetLibrary {\n    using SafeTransferLib for address;\n    using Address for address;\n\n    error NotEnoughReceived(address token, uint256 expected, uint256 received);\n\n    function forward(Asset calldata _self, address _to) internal {\n        if (_self.amount == 0) revert AmountMustNotBeZero(_self.token);\n\n        if (_self.token.isEth()) _to.safeTransferETH(_self.amount);\n        else _self.token.safeTransferFrom(msg.sender, _to, _self.amount);\n    }\n\n    function enforceReceived(Asset calldata _self) internal view {\n        if (_self.amount == 0) revert AmountMustNotBeZero(_self.token);\n\n        uint256 balance = _self.token.isEth()\n            ? address(this).balance\n            : _self.token.balanceOf(address(this));\n\n        if (balance < _self.amount) revert NotEnoughReceived(_self.token, _self.amount, balance);\n    }\n}\n"
      },
      "contracts/libraries/CalldataLibrary.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nlibrary CalldataLibrary {\n    uint256 private constant WORD_LENGTH = 32;\n\n    function appendWord(\n        bytes memory _payload,\n        address _word\n    ) internal pure returns (bytes memory result_) {\n        result_ = bytes.concat(_payload, bytes12(0), bytes20(_word));\n    }\n\n    function extractLastWordAsAddress(bytes calldata _payload) internal pure returns (address) {\n        uint256 start = _payload.length - WORD_LENGTH;\n        uint256 end = start + WORD_LENGTH;\n\n        bytes32 word = bytes32(_payload[start:end]);\n        return address(uint160(uint256(word)));\n    }\n}\n"
      },
      "contracts/libraries/CommandLibrary.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {Command} from \"contracts/interfaces/accountAbstraction/interpreter/Command.sol\";\nimport {SafeCall} from \"contracts/libraries/SafeCall.sol\";\n\n/**\n * @notice Utility to convert often-used methods into a Command object\n */\nlibrary CommandPresets {\n    function approve(\n        address _token,\n        address _to,\n        uint256 _amount\n    ) internal pure returns (Command memory cmd_) {\n        cmd_.target = _token;\n        cmd_.payload = abi.encodeCall(IERC20.approve, (_to, _amount));\n    }\n\n    function transfer(\n        address _token,\n        address _to,\n        uint256 _amount\n    ) internal pure returns (Command memory cmd_) {\n        cmd_.target = _token;\n        cmd_.payload = abi.encodeCall(IERC20.transfer, (_to, _amount));\n    }\n}\n\nlibrary CommandExecutor {\n    using SafeCall for Command[];\n\n    function execute(Command[] calldata _cmds) external {\n        _cmds.safeCallAll();\n    }\n}\n\nlibrary CommandLibrary {\n    using CommandLibrary for Command[];\n\n    function last(Command[] memory _self) internal pure returns (Command memory) {\n        return _self[_self.length - 1];\n    }\n\n    function asArray(Command memory _self) internal pure returns (Command[] memory result_) {\n        result_ = new Command[](1);\n        result_[0] = _self;\n    }\n\n    function concat(\n        Command memory _self,\n        Command memory _cmd\n    ) internal pure returns (Command[] memory result_) {\n        result_ = new Command[](2);\n        result_[0] = _self;\n        result_[1] = _cmd;\n    }\n\n    function concat(\n        Command memory _self,\n        Command[] memory _cmds\n    ) internal pure returns (Command[] memory result_) {\n        result_ = new Command[](_cmds.length + 1);\n        result_[0] = _self;\n        for (uint256 i = 1; i < result_.length; i++) {\n            result_[i] = _cmds[i - 1];\n        }\n    }\n\n    function append(\n        Command[] memory _self,\n        Command[] memory _cmds\n    ) internal pure returns (Command[] memory result_) {\n        result_ = new Command[](_self.length + _cmds.length);\n        uint256 i;\n        for (; i < _self.length; i++) {\n            result_[i] = _self[i];\n        }\n        for (; i < result_.length; i++) {\n            result_[i] = _cmds[i - _self.length];\n        }\n    }\n\n    function push(\n        Command[] memory _self,\n        Command memory _cmd\n    ) internal pure returns (Command[] memory result_) {\n        result_ = new Command[](_self.length + 1);\n        for (uint256 i; i < _self.length; i++) {\n            result_[i] = _self[i];\n        }\n        result_[_self.length] = _cmd;\n    }\n\n    function unshift(\n        Command[] memory _self,\n        Command memory _cmd\n    ) internal pure returns (Command[] memory result_) {\n        result_ = new Command[](1 + _self.length);\n        result_[0] = _cmd;\n        for (uint256 i = 1; i < result_.length; i++) {\n            result_[i] = _self[i - 1];\n        }\n    }\n\n    function unshift(\n        Command[] memory _self,\n        Command[] memory _cmds\n    ) internal pure returns (Command[] memory result_) {\n        result_ = new Command[](_cmds.length + _self.length);\n        uint256 i;\n        for (; i < _cmds.length; i++) {\n            result_[i] = _cmds[i];\n        }\n        for (; i < result_.length; i++) {\n            result_[i] = _self[i - _cmds.length];\n        }\n    }\n\n    function populateWithApprove(\n        Command memory _self,\n        address _token,\n        uint256 _amount\n    ) internal pure returns (Command[] memory result_) {\n        if (_amount != 0) {\n            result_ = CommandPresets.approve(_token, _self.target, _amount).concat(_self);\n        } else {\n            result_ = _self.asArray();\n        }\n    }\n\n    function populateWithRevokeAndApprove(\n        Command memory _self,\n        address _token,\n        uint256 _amount\n    ) internal pure returns (Command[] memory result_) {\n        return\n            CommandPresets.approve(_token, _self.target, 0).concat(\n                _self.populateWithApprove(_token, _amount)\n            );\n    }\n\n    function populateWithApprove(\n        Command[] memory _self,\n        address _token,\n        uint256 _amount\n    ) internal pure returns (Command[] memory result_) {\n        if (_amount != 0) {\n            result_ = _self.unshift(\n                CommandPresets.approve(_token, _self[_self.length - 1].target, _amount)\n            );\n        } else {\n            result_ = _self;\n        }\n    }\n\n    function populateWithApprove(\n        Command memory _self,\n        address[2] memory _tokens,\n        uint256[2] memory _amounts\n    ) internal pure returns (Command[] memory result_) {\n        if (_amounts[0] != 0 && _amounts[1] != 0) {\n            result_ = CommandPresets\n                .approve(_tokens[0], _self.target, _amounts[0])\n                .concat(CommandPresets.approve(_tokens[1], _self.target, _amounts[1]))\n                .push(_self);\n        } else {\n            if (_amounts[0] != 0) {\n                result_ = populateWithApprove(_self, _tokens[0], _amounts[0]);\n            } else {\n                result_ = populateWithApprove(_self, _tokens[1], _amounts[1]);\n            }\n        }\n    }\n\n    function populateWithApprove(\n        Command memory _self,\n        address[3] memory _tokens,\n        uint256[3] memory _amounts\n    ) internal pure returns (Command[] memory result_) {\n        if (_amounts[0] != 0 && _amounts[1] != 0 && _amounts[2] != 0) {\n            result_ = CommandPresets\n                .approve(_tokens[0], _self.target, _amounts[0])\n                .concat(CommandPresets.approve(_tokens[1], _self.target, _amounts[1]))\n                .push(CommandPresets.approve(_tokens[2], _self.target, _amounts[2]))\n                .push(_self);\n        } else {\n            if (_amounts[0] == 0) {\n                result_ = populateWithApprove(\n                    _self,\n                    [_tokens[1], _tokens[2]],\n                    [_amounts[1], _amounts[2]]\n                );\n            } else if (_amounts[1] == 0) {\n                result_ = populateWithApprove(\n                    _self,\n                    [_tokens[0], _tokens[2]],\n                    [_amounts[0], _amounts[2]]\n                );\n            } else {\n                result_ = populateWithApprove(\n                    _self,\n                    [_tokens[0], _tokens[1]],\n                    [_amounts[0], _amounts[1]]\n                );\n            }\n        }\n    }\n\n    function populateWithApprove(\n        Command memory _self,\n        address[4] memory _tokens,\n        uint256[4] memory _amounts\n    ) internal pure returns (Command[] memory result_) {\n        if (_amounts[0] != 0 && _amounts[1] != 0 && _amounts[2] != 0 && _amounts[3] != 0) {\n            result_ = CommandPresets\n                .approve(_tokens[0], _self.target, _amounts[0])\n                .concat(CommandPresets.approve(_tokens[1], _self.target, _amounts[1]))\n                .push(CommandPresets.approve(_tokens[2], _self.target, _amounts[2]))\n                .push(CommandPresets.approve(_tokens[3], _self.target, _amounts[3]))\n                .push(_self);\n        } else {\n            if (_amounts[0] == 0) {\n                result_ = populateWithApprove(\n                    _self,\n                    [_tokens[1], _tokens[2], _tokens[3]],\n                    [_amounts[1], _amounts[2], _amounts[3]]\n                );\n            } else if (_amounts[1] == 0) {\n                result_ = populateWithApprove(\n                    _self,\n                    [_tokens[0], _tokens[2], _tokens[3]],\n                    [_amounts[0], _amounts[2], _amounts[3]]\n                );\n            } else if (_amounts[2] == 0) {\n                result_ = populateWithApprove(\n                    _self,\n                    [_tokens[0], _tokens[1], _tokens[3]],\n                    [_amounts[0], _amounts[1], _amounts[3]]\n                );\n            } else {\n                result_ = populateWithApprove(\n                    _self,\n                    [_tokens[0], _tokens[1], _tokens[2]],\n                    [_amounts[0], _amounts[1], _amounts[2]]\n                );\n            }\n        }\n    }\n}\n"
      },
      "contracts/libraries/SafeCall.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.22;\n\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\nimport {Command} from \"contracts/interfaces/accountAbstraction/interpreter/Command.sol\";\n\n/**\n * @notice Safe methods performing a low-level calls that revert\n * if the call was not successful\n */\nlibrary SafeCall {\n    using Address for address;\n\n    function safeCallAll(Command[] memory _cmds) internal {\n        for (uint256 i; i < _cmds.length; i++) {\n            safeCall(_cmds[i]);\n        }\n    }\n\n    function safeCall(Command memory _cmd) internal returns (bytes memory result_) {\n        result_ = safeCall(_cmd.target, _cmd.value, _cmd.payload);\n    }\n\n    function safeCall(address _target, bytes memory _data) internal returns (bytes memory result_) {\n        result_ = safeCall(_target, 0, _data);\n    }\n\n    function safeCall(\n        address _target,\n        uint256 _value,\n        bytes memory _data\n    ) internal returns (bytes memory result_) {\n        result_ = _target.functionCallWithValue(_data, _value);\n    }\n\n    function safeDelegateCall(\n        address _target,\n        bytes memory _data\n    ) internal returns (bytes memory result_) {\n        result_ = _target.functionDelegateCall(_data);\n    }\n}\n"
      },
      "solady/src/utils/SafeTransferLib.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\n/// @dev Caution! This library won't check that a token has code, responsibility is delegated to the caller.\nlibrary SafeTransferLib {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                       CUSTOM ERRORS                        */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The ETH transfer has failed.\n    error ETHTransferFailed();\n\n    /// @dev The ERC20 `transferFrom` has failed.\n    error TransferFromFailed();\n\n    /// @dev The ERC20 `transfer` has failed.\n    error TransferFailed();\n\n    /// @dev The ERC20 `approve` has failed.\n    error ApproveFailed();\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                         CONSTANTS                          */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Suggested gas stipend for contract receiving ETH\n    /// that disallows any storage writes.\n    uint256 internal constant _GAS_STIPEND_NO_STORAGE_WRITES = 2300;\n\n    /// @dev Suggested gas stipend for contract receiving ETH to perform a few\n    /// storage reads and writes, but low enough to prevent griefing.\n    /// Multiply by a small constant (e.g. 2), if needed.\n    uint256 internal constant _GAS_STIPEND_NO_GRIEF = 100000;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                       ETH OPERATIONS                       */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Sends `amount` (in wei) ETH to `to`.\n    /// Reverts upon failure.\n    function safeTransferETH(address to, uint256 amount) internal {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Transfer the ETH and check if it succeeded or not.\n            if iszero(call(gas(), to, amount, 0, 0, 0, 0)) {\n                // Store the function selector of `ETHTransferFailed()`.\n                mstore(0x00, 0xb12d13eb)\n                // Revert with (offset, size).\n                revert(0x1c, 0x04)\n            }\n        }\n    }\n\n    /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.\n    /// The `gasStipend` can be set to a low enough value to prevent\n    /// storage writes or gas griefing.\n    ///\n    /// If sending via the normal procedure fails, force sends the ETH by\n    /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH.\n    ///\n    /// Reverts if the current contract has insufficient balance.\n    function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // If insufficient balance, revert.\n            if lt(selfbalance(), amount) {\n                // Store the function selector of `ETHTransferFailed()`.\n                mstore(0x00, 0xb12d13eb)\n                // Revert with (offset, size).\n                revert(0x1c, 0x04)\n            }\n            // Transfer the ETH and check if it succeeded or not.\n            if iszero(call(gasStipend, to, amount, 0, 0, 0, 0)) {\n                mstore(0x00, to) // Store the address in scratch space.\n                mstore8(0x0b, 0x73) // Opcode `PUSH20`.\n                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\n                // We can directly use `SELFDESTRUCT` in the contract creation.\n                // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758\n                if iszero(create(amount, 0x0b, 0x16)) {\n                    // For better gas estimation.\n                    if iszero(gt(gas(), 1000000)) { revert(0, 0) }\n                }\n            }\n        }\n    }\n\n    /// @dev Force sends `amount` (in wei) ETH to `to`, with a gas stipend\n    /// equal to `_GAS_STIPEND_NO_GRIEF`. This gas stipend is a reasonable default\n    /// for 99% of cases and can be overriden with the three-argument version of this\n    /// function if necessary.\n    ///\n    /// If sending via the normal procedure fails, force sends the ETH by\n    /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH.\n    ///\n    /// Reverts if the current contract has insufficient balance.\n    function forceSafeTransferETH(address to, uint256 amount) internal {\n        // Manually inlined because the compiler doesn't inline functions with branches.\n        /// @solidity memory-safe-assembly\n        assembly {\n            // If insufficient balance, revert.\n            if lt(selfbalance(), amount) {\n                // Store the function selector of `ETHTransferFailed()`.\n                mstore(0x00, 0xb12d13eb)\n                // Revert with (offset, size).\n                revert(0x1c, 0x04)\n            }\n            // Transfer the ETH and check if it succeeded or not.\n            if iszero(call(_GAS_STIPEND_NO_GRIEF, to, amount, 0, 0, 0, 0)) {\n                mstore(0x00, to) // Store the address in scratch space.\n                mstore8(0x0b, 0x73) // Opcode `PUSH20`.\n                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\n                // We can directly use `SELFDESTRUCT` in the contract creation.\n                // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758\n                if iszero(create(amount, 0x0b, 0x16)) {\n                    // For better gas estimation.\n                    if iszero(gt(gas(), 1000000)) { revert(0, 0) }\n                }\n            }\n        }\n    }\n\n    /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.\n    /// The `gasStipend` can be set to a low enough value to prevent\n    /// storage writes or gas griefing.\n    ///\n    /// Simply use `gasleft()` for `gasStipend` if you don't need a gas stipend.\n    ///\n    /// Note: Does NOT revert upon failure.\n    /// Returns whether the transfer of ETH is successful instead.\n    function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)\n        internal\n        returns (bool success)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Transfer the ETH and check if it succeeded or not.\n            success := call(gasStipend, to, amount, 0, 0, 0, 0)\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                      ERC20 OPERATIONS                      */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.\n    /// Reverts upon failure.\n    ///\n    /// The `from` account must have at least `amount` approved for\n    /// the current contract to manage.\n    function safeTransferFrom(address token, address from, address to, uint256 amount) internal {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n\n            mstore(0x60, amount) // Store the `amount` argument.\n            mstore(0x40, to) // Store the `to` argument.\n            mstore(0x2c, shl(96, from)) // Store the `from` argument.\n            // Store the function selector of `transferFrom(address,address,uint256)`.\n            mstore(0x0c, 0x23b872dd000000000000000000000000)\n\n            if iszero(\n                and( // The arguments of `and` are evaluated from right to left.\n                    // Set success to whether the call reverted, if not we check it either\n                    // returned exactly 1 (can't just be non-zero data), or had no return data.\n                    or(eq(mload(0x00), 1), iszero(returndatasize())),\n                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\n                )\n            ) {\n                // Store the function selector of `TransferFromFailed()`.\n                mstore(0x00, 0x7939f424)\n                // Revert with (offset, size).\n                revert(0x1c, 0x04)\n            }\n\n            mstore(0x60, 0) // Restore the zero slot to zero.\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /// @dev Sends all of ERC20 `token` from `from` to `to`.\n    /// Reverts upon failure.\n    ///\n    /// The `from` account must have at least `amount` approved for\n    /// the current contract to manage.\n    function safeTransferAllFrom(address token, address from, address to)\n        internal\n        returns (uint256 amount)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n\n            mstore(0x40, to) // Store the `to` argument.\n            mstore(0x2c, shl(96, from)) // Store the `from` argument.\n            // Store the function selector of `balanceOf(address)`.\n            mstore(0x0c, 0x70a08231000000000000000000000000)\n            if iszero(\n                and( // The arguments of `and` are evaluated from right to left.\n                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.\n                    staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)\n                )\n            ) {\n                // Store the function selector of `TransferFromFailed()`.\n                mstore(0x00, 0x7939f424)\n                // Revert with (offset, size).\n                revert(0x1c, 0x04)\n            }\n\n            // Store the function selector of `transferFrom(address,address,uint256)`.\n            mstore(0x00, 0x23b872dd)\n            // The `amount` argument is already written to the memory word at 0x6c.\n            amount := mload(0x60)\n\n            if iszero(\n                and( // The arguments of `and` are evaluated from right to left.\n                    // Set success to whether the call reverted, if not we check it either\n                    // returned exactly 1 (can't just be non-zero data), or had no return data.\n                    or(eq(mload(0x00), 1), iszero(returndatasize())),\n                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\n                )\n            ) {\n                // Store the function selector of `TransferFromFailed()`.\n                mstore(0x00, 0x7939f424)\n                // Revert with (offset, size).\n                revert(0x1c, 0x04)\n            }\n\n            mstore(0x60, 0) // Restore the zero slot to zero.\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.\n    /// Reverts upon failure.\n    function safeTransfer(address token, address to, uint256 amount) internal {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x14, to) // Store the `to` argument.\n            mstore(0x34, amount) // Store the `amount` argument.\n            // Store the function selector of `transfer(address,uint256)`.\n            mstore(0x00, 0xa9059cbb000000000000000000000000)\n\n            if iszero(\n                and( // The arguments of `and` are evaluated from right to left.\n                    // Set success to whether the call reverted, if not we check it either\n                    // returned exactly 1 (can't just be non-zero data), or had no return data.\n                    or(eq(mload(0x00), 1), iszero(returndatasize())),\n                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n                )\n            ) {\n                // Store the function selector of `TransferFailed()`.\n                mstore(0x00, 0x90b8ec18)\n                // Revert with (offset, size).\n                revert(0x1c, 0x04)\n            }\n            // Restore the part of the free memory pointer that was overwritten.\n            mstore(0x34, 0)\n        }\n    }\n\n    /// @dev Sends all of ERC20 `token` from the current contract to `to`.\n    /// Reverts upon failure.\n    function safeTransferAll(address token, address to) internal returns (uint256 amount) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.\n            mstore(0x20, address()) // Store the address of the current contract.\n            if iszero(\n                and( // The arguments of `and` are evaluated from right to left.\n                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.\n                    staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)\n                )\n            ) {\n                // Store the function selector of `TransferFailed()`.\n                mstore(0x00, 0x90b8ec18)\n                // Revert with (offset, size).\n                revert(0x1c, 0x04)\n            }\n\n            mstore(0x14, to) // Store the `to` argument.\n            // The `amount` argument is already written to the memory word at 0x34.\n            amount := mload(0x34)\n            // Store the function selector of `transfer(address,uint256)`.\n            mstore(0x00, 0xa9059cbb000000000000000000000000)\n\n            if iszero(\n                and( // The arguments of `and` are evaluated from right to left.\n                    // Set success to whether the call reverted, if not we check it either\n                    // returned exactly 1 (can't just be non-zero data), or had no return data.\n                    or(eq(mload(0x00), 1), iszero(returndatasize())),\n                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n                )\n            ) {\n                // Store the function selector of `TransferFailed()`.\n                mstore(0x00, 0x90b8ec18)\n                // Revert with (offset, size).\n                revert(0x1c, 0x04)\n            }\n            // Restore the part of the free memory pointer that was overwritten.\n            mstore(0x34, 0)\n        }\n    }\n\n    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.\n    /// Reverts upon failure.\n    function safeApprove(address token, address to, uint256 amount) internal {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x14, to) // Store the `to` argument.\n            mstore(0x34, amount) // Store the `amount` argument.\n            // Store the function selector of `approve(address,uint256)`.\n            mstore(0x00, 0x095ea7b3000000000000000000000000)\n\n            if iszero(\n                and( // The arguments of `and` are evaluated from right to left.\n                    // Set success to whether the call reverted, if not we check it either\n                    // returned exactly 1 (can't just be non-zero data), or had no return data.\n                    or(eq(mload(0x00), 1), iszero(returndatasize())),\n                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n                )\n            ) {\n                // Store the function selector of `ApproveFailed()`.\n                mstore(0x00, 0x3e3f8f73)\n                // Revert with (offset, size).\n                revert(0x1c, 0x04)\n            }\n            // Restore the part of the free memory pointer that was overwritten.\n            mstore(0x34, 0)\n        }\n    }\n\n    /// @dev Returns the amount of ERC20 `token` owned by `account`.\n    /// Returns zero if the `token` does not exist.\n    function balanceOf(address token, address account) internal view returns (uint256 amount) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x14, account) // Store the `account` argument.\n            // Store the function selector of `balanceOf(address)`.\n            mstore(0x00, 0x70a08231000000000000000000000000)\n            amount :=\n                mul(\n                    mload(0x20),\n                    and( // The arguments of `and` are evaluated from right to left.\n                        gt(returndatasize(), 0x1f), // At least 32 bytes returned.\n                        staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)\n                    )\n                )\n        }\n    }\n}\n"
      }
    },
    "settings": {
      "viaIR": false,
      "optimizer": {
        "enabled": true,
        "runs": 1000000
      },
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}