creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/release/infrastructure/price-feeds/primitives/NonStandardPrecisionSimulatedAggregator.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\n/*\n    This file is part of the Enzyme Protocol.\n\n    (c) Enzyme Council <council@enzyme.finance>\n\n    For the full license information, please view the LICENSE\n    file that was distributed with this source code.\n*/\n\npragma solidity 0.8.19;\n\nimport {IChainlinkAggregator} from \"../../../../external-interfaces/IChainlinkAggregator.sol\";\nimport {IChainlinkPriceFeedMixin} from \"./IChainlinkPriceFeedMixin.sol\";\n\n/// @title NonStandardPrecisionSimulatedAggregator Contract\n/// @author Enzyme Council <security@enzyme.finance>\n/// @notice A simulated aggregator to support a Chainlink-like aggregator that uses\n/// a non-standard number of decimals for precision\ncontract NonStandardPrecisionSimulatedAggregator {\n    enum ScaleType {\n        Up,\n        Down\n    }\n\n    error NegativeAnswer();\n\n    error NoScalingNeeded();\n\n    error UnsupportedRateAsset();\n\n    uint8 private constant STANDARD_ETH_RATE_DECIMALS = 18;\n    uint8 private constant STANDARD_USD_RATE_DECIMALS = 8;\n\n    IChainlinkAggregator private immutable AGGREGATOR;\n    int256 private immutable SCALE_FACTOR;\n    ScaleType private immutable SCALE_TYPE;\n    uint8 private immutable STANDARD_RATE_DECIMALS;\n\n    constructor(IChainlinkAggregator _aggregator, IChainlinkPriceFeedMixin.RateAsset _rateAsset) {\n        AGGREGATOR = _aggregator;\n\n        // Set the usual decimal precision used for Chainlink feeds of the given rate asset\n        uint8 standardRateDecimals;\n        if (_rateAsset == IChainlinkPriceFeedMixin.RateAsset.ETH) {\n            standardRateDecimals = STANDARD_ETH_RATE_DECIMALS;\n        } else if (_rateAsset == IChainlinkPriceFeedMixin.RateAsset.USD) {\n            standardRateDecimals = STANDARD_USD_RATE_DECIMALS;\n        } else {\n            revert UnsupportedRateAsset();\n        }\n        STANDARD_RATE_DECIMALS = standardRateDecimals;\n\n        // Set the scale type and factor to convert to the standard rate precision,\n        // given the actual aggregator's decimal precision\n        uint256 scaleFactorUint;\n        ScaleType scaleType;\n        uint8 aggregatorDecimals = _aggregator.decimals();\n        if (aggregatorDecimals > standardRateDecimals) {\n            scaleType = ScaleType.Down;\n            scaleFactorUint = 10 ** (aggregatorDecimals - standardRateDecimals);\n        } else if (aggregatorDecimals < standardRateDecimals) {\n            scaleType = ScaleType.Up;\n            scaleFactorUint = 10 ** (standardRateDecimals - aggregatorDecimals);\n        } else {\n            revert NoScalingNeeded();\n        }\n        SCALE_FACTOR = int256(scaleFactorUint);\n        SCALE_TYPE = scaleType;\n    }\n\n    /// @notice The decimals used for rate precision of this simulated aggregator\n    /// @return decimals_ The number of decimals\n    function decimals() external view returns (uint8 decimals_) {\n        return STANDARD_RATE_DECIMALS;\n    }\n\n    /// @notice The latest round data for this simulated aggregator\n    /// @return roundId_ The `roundId` value returned by the Chainlink aggregator\n    /// @return answer_ The `answer` value returned by the Chainlink aggregator, converted to standard rate decimals\n    /// @return startedAt_ The `startedAt` value returned by the Chainlink aggregator\n    /// @return updatedAt_ The `updatedAt` value returned by the Chainlink aggregator\n    /// @return answeredInRound_ The `answeredInRound` value returned by the Chainlink aggregator\n    /// @dev All values are returned directly from the target Chainlink-like aggregator,\n    /// other than `answer_`, which is converted to the standard decimal precision for the rate asset\n    /// and is given the local precision of `DECIMALS`.\n    function latestRoundData()\n        external\n        view\n        returns (uint80 roundId_, int256 answer_, uint256 startedAt_, uint256 updatedAt_, uint80 answeredInRound_)\n    {\n        int256 aggregatorAnswer;\n        (roundId_, aggregatorAnswer, startedAt_, updatedAt_, answeredInRound_) = AGGREGATOR.latestRoundData();\n\n        if (aggregatorAnswer < 0) {\n            revert NegativeAnswer();\n        }\n\n        if (SCALE_TYPE == ScaleType.Up) {\n            answer_ = aggregatorAnswer * SCALE_FACTOR;\n        } else {\n            answer_ = aggregatorAnswer / SCALE_FACTOR;\n        }\n\n        return (roundId_, answer_, startedAt_, updatedAt_, answeredInRound_);\n    }\n}\n"
      },
      "contracts/external-interfaces/IChainlinkAggregator.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\n/*\n    This file is part of the Enzyme Protocol.\n\n    (c) Enzyme Council <council@enzyme.finance>\n\n    For the full license information, please view the LICENSE\n    file that was distributed with this source code.\n*/\n\npragma solidity >=0.6.0 <0.9.0;\n\n/// @title IChainlinkAggregator Interface\n/// @author Enzyme Council <security@enzyme.finance>\ninterface IChainlinkAggregator {\n    function decimals() external view returns (uint8);\n\n    function latestRoundData() external view returns (uint80, int256, uint256, uint256, uint80);\n}\n"
      },
      "contracts/release/infrastructure/price-feeds/primitives/IChainlinkPriceFeedMixin.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\n\n/*\n    This file is part of the Enzyme Protocol.\n\n    (c) Enzyme Council <council@enzyme.finance>\n\n    For the full license information, please view the LICENSE\n    file that was distributed with this source code.\n*/\n\npragma solidity >=0.6.0 <0.9.0;\n\n/// @title IChainlinkPriceFeedMixin Interface\n/// @author Enzyme Council <security@enzyme.finance>\n/// @notice Interface for ChainlinkPriceFeedMixin\ninterface IChainlinkPriceFeedMixin {\n    enum RateAsset {\n        ETH,\n        USD\n    }\n\n    struct AggregatorInfo {\n        address aggregator;\n        RateAsset rateAsset;\n    }\n\n    function getAggregatorForPrimitive(address _primitive) external view returns (address aggregator_);\n\n    function getEthUsdAggregator() external view returns (address ethUsdAggregator_);\n\n    function getRateAssetForPrimitive(address _primitive) external view returns (RateAsset rateAsset_);\n\n    function getStaleRateThreshold() external view returns (uint256 staleRateThreshold_);\n\n    function getUnitForPrimitive(address _primitive) external view returns (uint256 unit_);\n\n    function getWethToken() external view returns (address wethToken_);\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "@openzeppelin/contracts/=lib/openzeppelin-solc-0.6/contracts/",
        "@uniswap/v3-core/=lib/uniswap-v3-core/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "forge-std/=lib/forge-std/src/",
        "openzeppelin-solc-0.6/=lib/openzeppelin-solc-0.6/contracts/",
        "openzeppelin-solc-0.7/=lib/openzeppelin-solc-0.7/contracts/",
        "openzeppelin-solc-0.8/=lib/openzeppelin-solc-0.8/contracts/",
        "uniswap-v3-core/=lib/uniswap-v3-core/",
        "uniswap-v3-core-0.8/=lib/uniswap-v3-core-0.8/",
        "uniswap-v3-periphery/=lib/uniswap-v3-periphery/contracts/",
        "uniswap-v3-periphery-0.8/=lib/uniswap-v3-periphery-0.8/contracts/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200,
        "details": {
          "yul": false
        }
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "none",
        "appendCBOR": false
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "viaIR": false,
      "libraries": {}
    }
  }}