creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "node_modules/@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\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, it is bubbled up by this\n     * function (like regular Solidity function calls).\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     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\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     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\n        }\n    }\n}\n"
      },
      "src/v0.8/operatorforwarder/AuthorizedForwarder.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nimport {ConfirmedOwnerWithProposal} from \"../shared/access/ConfirmedOwnerWithProposal.sol\";\nimport {AuthorizedReceiver} from \"./AuthorizedReceiver.sol\";\nimport {Address} from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// solhint-disable gas-custom-errors\ncontract AuthorizedForwarder is ConfirmedOwnerWithProposal, AuthorizedReceiver {\n  using Address for address;\n\n  // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i\n  address public immutable linkToken;\n\n  event OwnershipTransferRequestedWithMessage(address indexed from, address indexed to, bytes message);\n\n  constructor(\n    address link,\n    address owner,\n    address recipient,\n    bytes memory message\n  ) ConfirmedOwnerWithProposal(owner, recipient) {\n    require(link != address(0), \"Link token cannot be a zero address\");\n    linkToken = link;\n    if (recipient != address(0)) {\n      emit OwnershipTransferRequestedWithMessage(owner, recipient, message);\n    }\n  }\n\n  string public constant typeAndVersion = \"AuthorizedForwarder 1.1.0\";\n\n  // @notice Forward a call to another contract\n  // @dev Only callable by an authorized sender\n  // @param to address\n  // @param data to forward\n  function forward(address to, bytes calldata data) external validateAuthorizedSender {\n    require(to != linkToken, \"Cannot forward to Link token\");\n    _forward(to, data);\n  }\n\n  //  @notice Forward multiple calls to other contracts in a multicall style\n  //  @dev Only callable by an authorized sender\n  //  @param tos An array of addresses to forward the calls to\n  //  @param datas An array of data to forward to each corresponding address\n  function multiForward(address[] calldata tos, bytes[] calldata datas) external validateAuthorizedSender {\n    require(tos.length == datas.length, \"Arrays must have the same length\");\n\n    for (uint256 i = 0; i < tos.length; ++i) {\n      address to = tos[i];\n      require(to != linkToken, \"Cannot forward to Link token\");\n\n      // Perform the forward operation\n      _forward(to, datas[i]);\n    }\n  }\n\n  // @notice Forward a call to another contract\n  // @dev Only callable by the owner\n  // @param to address\n  // @param data to forward\n  function ownerForward(address to, bytes calldata data) external onlyOwner {\n    _forward(to, data);\n  }\n\n  // @notice Transfer ownership with instructions for recipient\n  // @param to address proposed recipient of ownership\n  // @param message instructions for recipient upon accepting ownership\n  function transferOwnershipWithMessage(address to, bytes calldata message) external {\n    transferOwnership(to);\n    emit OwnershipTransferRequestedWithMessage(msg.sender, to, message);\n  }\n\n  // @notice concrete implementation of AuthorizedReceiver\n  // @return bool of whether sender is authorized\n  function _canSetAuthorizedSenders() internal view override returns (bool) {\n    return owner() == msg.sender;\n  }\n\n  // @notice common forwarding functionality and validation\n  function _forward(address to, bytes calldata data) private {\n    require(to.isContract(), \"Must forward to a contract\");\n    // solhint-disable-next-line avoid-low-level-calls\n    (bool success, bytes memory result) = to.call(data);\n    if (!success) {\n      if (result.length == 0) revert(\"Forwarded call reverted without reason\");\n      assembly {\n        revert(add(32, result), mload(result))\n      }\n    }\n  }\n}\n"
      },
      "src/v0.8/operatorforwarder/AuthorizedReceiver.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nimport {IAuthorizedReceiver} from \"./interfaces/IAuthorizedReceiver.sol\";\n\n// solhint-disable gas-custom-errors\nabstract contract AuthorizedReceiver is IAuthorizedReceiver {\n  mapping(address sender => bool authorized) private s_authorizedSenders;\n  address[] private s_authorizedSenderList;\n\n  event AuthorizedSendersChanged(address[] senders, address changedBy);\n\n  // @notice Sets the fulfillment permission for a given node. Use `true` to allow, `false` to disallow.\n  // @param senders The addresses of the authorized Chainlink node\n  function setAuthorizedSenders(address[] calldata senders) external override validateAuthorizedSenderSetter {\n    require(senders.length > 0, \"Must have at least 1 sender\");\n    // Set previous authorized senders to false\n    uint256 authorizedSendersLength = s_authorizedSenderList.length;\n    for (uint256 i = 0; i < authorizedSendersLength; ++i) {\n      s_authorizedSenders[s_authorizedSenderList[i]] = false;\n    }\n    // Set new to true\n    for (uint256 i = 0; i < senders.length; ++i) {\n      require(s_authorizedSenders[senders[i]] == false, \"Must not have duplicate senders\");\n      s_authorizedSenders[senders[i]] = true;\n    }\n    // Replace list\n    s_authorizedSenderList = senders;\n    emit AuthorizedSendersChanged(senders, msg.sender);\n  }\n\n  // @notice Retrieve a list of authorized senders\n  // @return array of addresses\n  function getAuthorizedSenders() external view override returns (address[] memory) {\n    return s_authorizedSenderList;\n  }\n\n  // @notice Use this to check if a node is authorized for fulfilling requests\n  // @param sender The address of the Chainlink node\n  // @return The authorization status of the node\n  function isAuthorizedSender(address sender) public view override returns (bool) {\n    return s_authorizedSenders[sender];\n  }\n\n  // @notice customizable guard of who can update the authorized sender list\n  // @return bool whether sender can update authorized sender list\n  function _canSetAuthorizedSenders() internal virtual returns (bool);\n\n  // @notice validates the sender is an authorized sender\n  function _validateIsAuthorizedSender() internal view {\n    require(isAuthorizedSender(msg.sender), \"Not authorized sender\");\n  }\n\n  // @notice prevents non-authorized addresses from calling this method\n  modifier validateAuthorizedSender() {\n    _validateIsAuthorizedSender();\n    _;\n  }\n\n  // @notice prevents non-authorized addresses from calling this method\n  modifier validateAuthorizedSenderSetter() {\n    require(_canSetAuthorizedSenders(), \"Cannot set authorized senders\");\n    _;\n  }\n}\n"
      },
      "src/v0.8/operatorforwarder/interfaces/IAuthorizedReceiver.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IAuthorizedReceiver {\n  function isAuthorizedSender(address sender) external view returns (bool);\n\n  function getAuthorizedSenders() external returns (address[] memory);\n\n  function setAuthorizedSenders(address[] calldata senders) external;\n}\n"
      },
      "src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IOwnable} from \"../interfaces/IOwnable.sol\";\n\n/// @title The ConfirmedOwner contract\n/// @notice A contract with helpers for basic contract ownership.\ncontract ConfirmedOwnerWithProposal is IOwnable {\n  address private s_owner;\n  address private s_pendingOwner;\n\n  event OwnershipTransferRequested(address indexed from, address indexed to);\n  event OwnershipTransferred(address indexed from, address indexed to);\n\n  constructor(address newOwner, address pendingOwner) {\n    // solhint-disable-next-line gas-custom-errors\n    require(newOwner != address(0), \"Cannot set owner to zero\");\n\n    s_owner = newOwner;\n    if (pendingOwner != address(0)) {\n      _transferOwnership(pendingOwner);\n    }\n  }\n\n  /// @notice Allows an owner to begin transferring ownership to a new address.\n  function transferOwnership(address to) public override onlyOwner {\n    _transferOwnership(to);\n  }\n\n  /// @notice Allows an ownership transfer to be completed by the recipient.\n  function acceptOwnership() external override {\n    // solhint-disable-next-line gas-custom-errors\n    require(msg.sender == s_pendingOwner, \"Must be proposed owner\");\n\n    address oldOwner = s_owner;\n    s_owner = msg.sender;\n    s_pendingOwner = address(0);\n\n    emit OwnershipTransferred(oldOwner, msg.sender);\n  }\n\n  /// @notice Get the current owner\n  function owner() public view override returns (address) {\n    return s_owner;\n  }\n\n  /// @notice validate, transfer ownership, and emit relevant events\n  function _transferOwnership(address to) private {\n    // solhint-disable-next-line gas-custom-errors\n    require(to != msg.sender, \"Cannot transfer to self\");\n\n    s_pendingOwner = to;\n\n    emit OwnershipTransferRequested(s_owner, to);\n  }\n\n  /// @notice validate access\n  function _validateOwnership() internal view {\n    // solhint-disable-next-line gas-custom-errors\n    require(msg.sender == s_owner, \"Only callable by owner\");\n  }\n\n  /// @notice Reverts if called by anyone other than the contract owner.\n  modifier onlyOwner() {\n    _validateOwnership();\n    _;\n  }\n}\n"
      },
      "src/v0.8/shared/interfaces/IOwnable.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IOwnable {\n  function owner() external returns (address);\n\n  function transferOwnership(address recipient) external;\n\n  function acceptOwnership() external;\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "ds-test/=foundry-lib/forge-std/lib/ds-test/src/",
        "forge-std/=foundry-lib/forge-std/src/",
        "@openzeppelin/=node_modules/@openzeppelin/",
        "hardhat/=node_modules/hardhat/",
        "@eth-optimism/=node_modules/@eth-optimism/",
        "@scroll-tech/=node_modules/@scroll-tech/",
        "erc4626-tests/=foundry-lib/openzeppelin-contracts/lib/erc4626-tests/",
        "openzeppelin-contracts/=foundry-lib/openzeppelin-contracts/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 1000000
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "none",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "viaIR": false,
      "libraries": {}
    }
  }}