creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/forwarders/DSROracleForwarderArbitrumOne.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport { XChainForwarders } from 'xchain-helpers/XChainForwarders.sol';\n\nimport { DSROracleForwarderBase } from './DSROracleForwarderBase.sol';\n\ncontract DSROracleForwarderArbitrumOne is DSROracleForwarderBase {\n\n    constructor(address _pot, address _l2Oracle) DSROracleForwarderBase(_pot, _l2Oracle) {\n        // Intentionally left blank\n    }\n\n    function refresh(\n        uint256 gasLimit,\n        uint256 maxFeePerGas,\n        uint256 baseFee\n    ) public payable {\n        XChainForwarders.sendMessageArbitrumOne(\n            address(l2Oracle),\n            _packMessage(),\n            gasLimit,\n            maxFeePerGas,\n            baseFee\n        );\n    }\n\n}\n"
      },
      "lib/xchain-helpers/src/XChainForwarders.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\npragma solidity ^0.8.0;\n\ninterface ICrossDomainOptimism {\n    function sendMessage(address _target, bytes calldata _message, uint32 _gasLimit) external;\n}\n\ninterface ICrossDomainArbitrum {\n    function createRetryableTicket(\n        address to,\n        uint256 l2CallValue,\n        uint256 maxSubmissionCost,\n        address excessFeeRefundAddress,\n        address callValueRefundAddress,\n        uint256 gasLimit,\n        uint256 maxFeePerGas,\n        bytes calldata data\n    ) external payable returns (uint256);\n    function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee) external view returns (uint256);\n}\n\ninterface ICrossDomainGnosis {\n    function requireToPassMessage(address _contract, bytes memory _data, uint256 _gas) external returns (bytes32);\n}\n\ninterface ICrossDomainZkEVM {\n    function bridgeMessage(\n        uint32 destinationNetwork,\n        address destinationAddress,\n        bool forceUpdateGlobalExitRoot,\n        bytes calldata metadata\n    ) external payable;\n}\n\n/**\n * @title XChainForwarders\n * @notice Helper functions to abstract over L1 -> L2 message passing.\n * @dev General structure is sendMessageXXX(target, message, gasLimit) where XXX is the remote domain name (IE OptimismMainnet, ArbitrumOne, Base, etc).\n */\nlibrary XChainForwarders {\n\n    /// ================================ Optimism Style ================================\n\n    function sendMessageOptimism(\n        address l1CrossDomain,\n        address target,\n        bytes memory message,\n        uint256 gasLimit\n    ) internal {\n        ICrossDomainOptimism(l1CrossDomain).sendMessage(\n            target,\n            message,\n            uint32(gasLimit)\n        );\n    }\n\n    function sendMessageOptimismMainnet(\n        address target,\n        bytes memory message,\n        uint256 gasLimit\n    ) internal {\n        sendMessageOptimism(\n            0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1,\n            target,\n            message,\n            uint32(gasLimit)\n        );\n    }\n\n    function sendMessageBase(\n        address target,\n        bytes memory message,\n        uint256 gasLimit\n    ) internal {\n        sendMessageOptimism(\n            0x866E82a600A1414e583f7F13623F1aC5d58b0Afa,\n            target,\n            message,\n            uint32(gasLimit)\n        );\n    }\n\n    /// ================================ Arbitrum Style ================================\n\n    function sendMessageArbitrum(\n        address l1CrossDomain,\n        address target,\n        bytes memory message,\n        uint256 gasLimit,\n        uint256 maxFeePerGas,\n        uint256 baseFee\n    ) internal {\n        uint256 maxSubmission = ICrossDomainArbitrum(l1CrossDomain).calculateRetryableSubmissionFee(message.length, baseFee);\n        uint256 maxRedemption = gasLimit * maxFeePerGas;\n        ICrossDomainArbitrum(l1CrossDomain).createRetryableTicket{value: maxSubmission + maxRedemption}(\n            target,\n            0, // we always assume that l2CallValue = 0\n            maxSubmission,\n            address(0), // burn the excess gas\n            address(0), // burn the excess gas\n            gasLimit,\n            maxFeePerGas,\n            message\n        );\n    }\n\n    function sendMessageArbitrumOne(\n        address target,\n        bytes memory message,\n        uint256 gasLimit,\n        uint256 maxFeePerGas,\n        uint256 baseFee\n    ) internal {\n        sendMessageArbitrum(\n            0x4Dbd4fc535Ac27206064B68FfCf827b0A60BAB3f,\n            target,\n            message,\n            gasLimit,\n            maxFeePerGas,\n            baseFee\n        );\n    }\n\n    function sendMessageArbitrumNova(\n        address target,\n        bytes memory message,\n        uint256 gasLimit,\n        uint256 maxFeePerGas,\n        uint256 baseFee\n    ) internal {\n        sendMessageArbitrum(\n            0xc4448b71118c9071Bcb9734A0EAc55D18A153949,\n            target,\n            message,\n            gasLimit,\n            maxFeePerGas,\n            baseFee\n        );\n    }\n\n    /// ================================ Gnosis ================================\n\n    function sendMessageGnosis(\n        address l1CrossDomain,\n        address target,\n        bytes memory message,\n        uint256 gasLimit\n    ) internal {\n        ICrossDomainGnosis(l1CrossDomain).requireToPassMessage(\n            target,\n            message,\n            gasLimit\n        );\n    }\n\n    function sendMessageGnosis(\n        address target,\n        bytes memory message,\n        uint256 gasLimit\n    ) internal {\n        sendMessageGnosis(\n            0x4C36d2919e407f0Cc2Ee3c993ccF8ac26d9CE64e,\n            target,\n            message,\n            gasLimit\n        );\n    }\n\n    /// ================================ zkEVM ================================\n\n    function sendMessageZkEVM(\n        address l1CrossDomain,\n        uint32 destinationNetworkId,\n        address destinationAddress,\n        bool forceUpdateGlobalExitRoot,\n        bytes memory metadata\n    ) internal {\n        ICrossDomainZkEVM(l1CrossDomain).bridgeMessage(\n            destinationNetworkId,\n            destinationAddress,\n            forceUpdateGlobalExitRoot,\n            metadata\n        );\n    }\n\n    function sendMessageZkEVM(\n        address destinationAddress,\n        bytes memory metadata\n    ) internal {\n        sendMessageZkEVM(\n            0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe,\n            1,\n            destinationAddress,\n            true,\n            metadata\n        );\n    }\n\n}\n"
      },
      "src/forwarders/DSROracleForwarderBase.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport { XChainForwarders } from 'xchain-helpers/XChainForwarders.sol';\n\nimport { DSROracleForwarder } from './DSROracleForwarder.sol';\n\ncontract DSROracleForwarderBase is DSROracleForwarder {\n\n    constructor(address _pot, address _l2Oracle) DSROracleForwarder(_pot, _l2Oracle) {\n        // Intentionally left blank\n    }\n\n    function refresh(uint256 gasLimit) public {\n        XChainForwarders.sendMessageBase(\n            address(l2Oracle),\n            _packMessage(),\n            gasLimit\n        );\n    }\n\n}\n"
      },
      "src/forwarders/DSROracleForwarder.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport { IDSRAuthOracle, IDSROracle } from '../interfaces/IDSRAuthOracle.sol';\nimport { IPot }                       from '../interfaces/IPot.sol';\n\n/**\n * @title  DSROracleForwarder\n * @notice Base contract for relaying pot data messages cross-chain.\n */\nabstract contract DSROracleForwarder {\n\n    IPot               public immutable pot;\n    address            public immutable l2Oracle;\n    \n    IDSROracle.PotData public _lastSeenPotData;\n\n    constructor(address _pot, address _l2Oracle) {\n        pot      = IPot(_pot);\n        l2Oracle = _l2Oracle;\n    }\n\n    function _packMessage() internal returns (bytes memory) {\n        IDSROracle.PotData memory potData = IDSROracle.PotData({\n            dsr: uint96(pot.dsr()),\n            chi: uint120(pot.chi()),\n            rho: uint40(pot.rho())\n        });\n        _lastSeenPotData = potData;\n        return abi.encodeCall(\n            IDSRAuthOracle.setPotData,\n            (potData)\n        );\n    }\n\n    function getLastSeenPotData() external view returns (IDSROracle.PotData memory) {\n        return _lastSeenPotData;\n    }\n\n    function getLastSeenDSR() external view returns (uint256) {\n        return _lastSeenPotData.dsr;\n    }\n\n    function getLastSeenChi() external view returns (uint256) {\n        return _lastSeenPotData.chi;\n    }\n\n    function getLastSeenRho() external view returns (uint256) {\n        return _lastSeenPotData.rho;\n    }\n\n}\n"
      },
      "src/interfaces/IDSRAuthOracle.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\npragma solidity >=0.8.0;\n\nimport { IDSROracle } from './IDSROracle.sol';\n\n/**\n * @title  IDSRAuthOracle\n * @notice Consolidated DSR reporting along with some convenience functions.\n */\ninterface IDSRAuthOracle is IDSROracle {\n\n    /** \n     * @notice Emitted when the maxDSR is updated.\n     */\n    event SetMaxDSR(uint256 maxDSR);\n\n    /**\n     * @notice The data provider role.\n     */\n    function DATA_PROVIDER_ROLE() external view returns (bytes32);\n\n    /**\n     * @notice Get the max dsr.\n     */\n    function maxDSR() external view returns (uint256);\n\n    /**\n     * @notice Set the max dsr.\n     * @param  maxDSR The max dsr.\n     * @dev    Only callable by the admin role.\n     */\n    function setMaxDSR(uint256 maxDSR) external;\n\n    /**\n     * @notice Update the pot data.\n     * @param  data The max dsr.\n     * @dev    Only callable by the data provider role.\n     */\n    function setPotData(IDSROracle.PotData calldata data) external;\n\n}\n"
      },
      "src/interfaces/IPot.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\npragma solidity >=0.8.0;\n\ninterface IPot {\n    function dsr() external view returns (uint256);\n    function chi() external view returns (uint256);\n    function rho() external view returns (uint256);\n}\n"
      },
      "src/interfaces/IDSROracle.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\npragma solidity >=0.8.0;\n\n/**\n * @title  IDSROracle\n * @notice Consolidated DSR reporting along with some convenience functions.\n */\ninterface IDSROracle {\n\n    struct PotData {\n        uint96  dsr;  // Dai Savings Rate in per-second value [ray]\n        uint120 chi;  // Last computed conversion rate [ray]\n        uint40  rho;  // Last computed timestamp [seconds]\n    }\n\n    /**\n     * @notice Emitted when the PotData is updated.\n     * @param  nextData The new PotData struct.\n     */\n    event SetPotData(PotData nextData);\n\n    /**\n     * @notice Retrieve the current PotData: dsr, chi, and rho.\n     * @return The current PotData struct.\n     */\n    function getPotData() external view returns (PotData memory);\n\n    /**\n     * @notice Get the current Dai Savings Rate.\n     * @return The Dai Savings Rate in per-second value [ray].\n     */\n    function getDSR() external view returns (uint256);\n\n    /**\n     * @notice Get the last computed conversion rate.\n     * @return The last computed conversion rate [ray].\n     */\n    function getChi() external view returns (uint256);\n\n    /**\n     * @notice Get the last computed timestamp.\n     * @return The last computed timestamp [seconds].\n     */\n    function getRho() external view returns (uint256);\n\n    /**\n     * @notice Get the Annual Percentage Rate.\n     * @return The APR.\n     */\n    function getAPR() external view returns (uint256);\n\n    /**\n     * @notice Get the conversion rate at the current timestamp.\n     * @return The conversion rate.\n     */\n    function getConversionRate() external view returns (uint256);\n\n    /**\n     * @notice Get the conversion rate at a specified timestamp.\n     * @dev    Timestamp must be greater than or equal to the current timestamp.\n     * @param  timestamp The timestamp at which to retrieve the conversion rate.\n     * @return The conversion rate.\n     */\n    function getConversionRate(uint256 timestamp) external view returns (uint256);\n\n    /**\n     * @notice Get the binomial approximated conversion rate at the current timestamp.\n     * @return The binomial approximated conversion rate.\n     */\n    function getConversionRateBinomialApprox() external view returns (uint256);\n\n    /**\n     * @notice Get the binomial approximated conversion rate at a specified timestamp.\n     * @dev    Timestamp must be greater than or equal to the current timestamp.\n     * @param  timestamp The timestamp at which to retrieve the binomial approximated conversion rate.\n     * @return The binomial approximated conversion rate.\n     */\n    function getConversionRateBinomialApprox(uint256 timestamp) external view returns (uint256);\n\n    /**\n     * @notice Get the linear approximated conversion rate at the current timestamp.\n     * @return The linear approximated conversion rate.\n     */\n    function getConversionRateLinearApprox() external view returns (uint256);\n\n    /**\n     * @notice Get the linear approximated conversion rate at a specified timestamp.\n     * @dev    Timestamp must be greater than or equal to the current timestamp.\n     * @param  timestamp The timestamp at which to retrieve the linear approximated conversion rate.\n     * @return The linear approximated conversion rate.\n     */\n    function getConversionRateLinearApprox(uint256 timestamp) external view returns (uint256);\n\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
        "forge-std/=lib/forge-std/src/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "sparklend-address-registry/=lib/sparklend-address-registry/",
        "xchain-helpers/=lib/xchain-helpers/src/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 100000
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "viaIR": false,
      "libraries": {}
    }
  }}