{"file_path":"src/ChainlinkOracle.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity 0.8.21;\n\nimport {IChainlinkOracle} from \"./interfaces/IChainlinkOracle.sol\";\nimport {IOracle} from \"../lib/morpho-blue/src/interfaces/IOracle.sol\";\n\nimport {AggregatorV3Interface, ChainlinkDataFeedLib} from \"./libraries/ChainlinkDataFeedLib.sol\";\nimport {IERC4626, VaultLib} from \"./libraries/VaultLib.sol\";\nimport {ErrorsLib} from \"./libraries/ErrorsLib.sol\";\nimport {Math} from \"../lib/openzeppelin-contracts/contracts/utils/math/Math.sol\";\n\n/// @title ChainlinkOracle\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Morpho Blue oracle using Chainlink-compliant feeds.\ncontract ChainlinkOracle is IChainlinkOracle {\n    using Math for uint256;\n    using VaultLib for IERC4626;\n    using ChainlinkDataFeedLib for AggregatorV3Interface;\n\n    /* IMMUTABLES */\n\n    /// @inheritdoc IChainlinkOracle\n    IERC4626 public immutable VAULT;\n\n    /// @inheritdoc IChainlinkOracle\n    uint256 public immutable VAULT_CONVERSION_SAMPLE;\n\n    /// @inheritdoc IChainlinkOracle\n    AggregatorV3Interface public immutable BASE_FEED_1;\n\n    /// @inheritdoc IChainlinkOracle\n    AggregatorV3Interface public immutable BASE_FEED_2;\n\n    /// @inheritdoc IChainlinkOracle\n    AggregatorV3Interface public immutable QUOTE_FEED_1;\n\n    /// @inheritdoc IChainlinkOracle\n    AggregatorV3Interface public immutable QUOTE_FEED_2;\n\n    /// @inheritdoc IChainlinkOracle\n    uint256 public immutable SCALE_FACTOR;\n\n    /* CONSTRUCTOR */\n\n    /// @dev Here is the list of assumptions that guarantees the oracle behaves as expected:\n    /// - Feeds are either Chainlink-compliant or the address zero.\n    /// - Feeds have the same behavioral assumptions as Chainlink's.\n    /// - Feeds are set in the correct order.\n    /// - Decimals passed as argument are correct.\n    /// - The vault's sample shares quoted as assets and the base feed prices don't overflow when multiplied.\n    /// - The quote feed prices don't overflow when multiplied.\n    /// - The vault, if set, is ERC4626-compliant.\n    /// @param vault Vault. Pass address zero to omit this parameter.\n    /// @param baseFeed1 First base feed. Pass address zero if the price = 1.\n    /// @param baseFeed2 Second base feed. Pass address zero if the price = 1.\n    /// @param quoteFeed1 First quote feed. Pass address zero if the price = 1.\n    /// @param quoteFeed2 Second quote feed. Pass address zero if the price = 1.\n    /// @param vaultConversionSample The sample amount of vault shares used to convert to the underlying asset.\n    /// Pass 1 if the oracle does not use a vault. Should be chosen such that converting `vaultConversionSample` to\n    /// assets has enough precision.\n    /// @param baseTokenDecimals Base token decimals.\n    /// @param quoteTokenDecimals Quote token decimals.\n    constructor(\n        IERC4626 vault,\n        AggregatorV3Interface baseFeed1,\n        AggregatorV3Interface baseFeed2,\n        AggregatorV3Interface quoteFeed1,\n        AggregatorV3Interface quoteFeed2,\n        uint256 vaultConversionSample,\n        uint256 baseTokenDecimals,\n        uint256 quoteTokenDecimals\n    ) {\n        // The ERC4626 vault parameter is used to price `VAULT_CONVERSION_SAMPLE` of its shares, so it requires dividing\n        // by that number, hence the division by `VAULT_CONVERSION_SAMPLE` in the `SCALE_FACTOR` definition.\n        // Verify that vault = address(0) => vaultConversionSample = 1.\n        require(\n            address(vault) != address(0) || vaultConversionSample == 1, ErrorsLib.VAULT_CONVERSION_SAMPLE_IS_NOT_ONE\n        );\n        require(vaultConversionSample != 0, ErrorsLib.VAULT_CONVERSION_SAMPLE_IS_ZERO);\n\n        VAULT = vault;\n        VAULT_CONVERSION_SAMPLE = vaultConversionSample;\n        BASE_FEED_1 = baseFeed1;\n        BASE_FEED_2 = baseFeed2;\n        QUOTE_FEED_1 = quoteFeed1;\n        QUOTE_FEED_2 = quoteFeed2;\n\n        // In the following comment, we explain the general case (where we assume that no feed is the address zero)\n        // how to scale the output price as Morpho Blue expects, given the input feed prices.\n        // Similar explanations would hold in the case where some of the feeds are the address zero.\n\n        // Let B1, B2, Q1, Q2, C be 5 assets, each respectively having dB1, dB2, dQ1, dQ2, dC decimals.\n        // Let pB1 and pB2 be the base prices, and pQ1 and pQ2 the quote prices, so that:\n        // - pB1 is the quantity of 1e(dB2) assets B2 that can be exchanged for 1e(dB1) assets B1.\n        // - pB2 is the quantity of 1e(dC) assets C that can be exchanged for 1e(dB2) assets B2.\n        // - pQ1 is the quantity of 1e(dQ2) assets Q2 that can be exchanged for 1e(dQ1) assets Q1.\n        // - pQ2 is the quantity of 1e(dC) assets C that can be exchanged for 1e(dQ2) assets B2.\n\n        // Morpho Blue expects `price()` to be the quantity of 1 asset Q1 that can be exchanged for 1 asset B1,\n        // scaled by 1e36:\n        // 1e36 * (pB1 * 1e(dB2 - dB1)) * (pB2 * 1e(dC - dB2)) / ((pQ1 * 1e(dQ2 - dQ1)) * (pQ2 * 1e(dC - dQ2)))\n        // = 1e36 * (pB1 * 1e(-dB1) * pB2) / (pQ1 * 1e(-dQ1) * pQ2)\n\n        // Let fpB1, fpB2, fpQ1, fpQ2 be the feed precision of the respective prices pB1, pB2, pQ1, pQ2.\n        // Chainlink feeds return pB1 * 1e(fpB1), pB2 * 1e(fpB2), pQ1 * 1e(fpQ1) and pQ2 * 1e(fpQ2).\n\n        // Based on the implementation of `price()` below, the value of `SCALE_FACTOR` should thus satisfy:\n        // (pB1 * 1e(fpB1)) * (pB2 * 1e(fpB2)) * SCALE_FACTOR / ((pQ1 * 1e(fpQ1)) * (pQ2 * 1e(fpQ2)))\n        // = 1e36 * (pB1 * 1e(-dB1) * pB2) / (pQ1 * 1e(-dQ1) * pQ2)\n\n        // So SCALE_FACTOR = 1e36 * 1e(-dB1) * 1e(dQ1) * 1e(-fpB1) * 1e(-fpB2) * 1e(fpQ1) * 1e(fpQ2)\n        //                 = 1e(36 + dQ1 + fpQ1 + fpQ2 - dB1 - fpB1 - fpB2)\n        SCALE_FACTOR = 10\n            ** (\n                36 + quoteTokenDecimals + quoteFeed1.getDecimals() + quoteFeed2.getDecimals() - baseTokenDecimals\n                    - baseFeed1.getDecimals() - baseFeed2.getDecimals()\n            ) / vaultConversionSample;\n    }\n\n    /* PRICE */\n\n    /// @inheritdoc IOracle\n    function price() external view returns (uint256) {\n        return SCALE_FACTOR.mulDiv(\n            VAULT.getAssets(VAULT_CONVERSION_SAMPLE) * BASE_FEED_1.getPrice() * BASE_FEED_2.getPrice(),\n            QUOTE_FEED_1.getPrice() * QUOTE_FEED_2.getPrice()\n        );\n    }\n}\n","deployed_bytecode":"0x60806040818152600436101561001457600080fd5b600091823560e01c908163411557d1146104455750806356095e11146103d7578063a035b1fe14610277578063acfbd39e14610209578063ce4b5bbe146101b1578063d6c843ca14610159578063dc53858c146100eb5763f50a47181461007a57600080fd5b346100e757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e7576020905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000fdfd9c85ad200c506cf9e21f1fd8dd01932fbb23168152f35b5080fd5b50346100e757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e7576020905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f4030086522a5beea4988f8ca5b36dbc97bee88c168152f35b50346100e757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e757602090517f00000000000000000000000000000000000000000000000000000000000000018152f35b50346100e757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e757602090517f00000000000000000000000000000000000000000052b7d2dcc80cd2e40000008152f35b50346100e757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e7576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346100e757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e7576020906103d061035461032b6102fc7f00000000000000000000000000000000000000000000000000000000000000017f0000000000000000000000000000000000000000000000000000000000000000610821565b6103257f000000000000000000000000fdfd9c85ad200c506cf9e21f1fd8dd01932fbb2361067c565b906104b3565b6103257f000000000000000000000000f4030086522a5beea4988f8ca5b36dbc97bee88c61067c565b6103a96103807f0000000000000000000000003e7d1eab13ad0104d2750b8863b489d65364e32d61067c565b6103257f000000000000000000000000000000000000000000000000000000000000000061067c565b907f00000000000000000000000000000000000000000052b7d2dcc80cd2e40000006104f5565b9051908152f35b50346100e757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e7576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000003e7d1eab13ad0104d2750b8863b489d65364e32d168152f35b8390346100e757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e75760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b818102929181159184041417156104c657565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9091828202917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848209938380861095039480860395146105b357848311156105895782910981600003821680920460028082600302188083028203028083028203028083028203028083028203028083028203028092029003029360018380600003040190848311900302920304170290565b60046040517f227bc153000000000000000000000000000000000000000000000000000000008152fd5b5050809250156105c1570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761063157604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b519069ffffffffffffffffffff8216820361067757565b600080fd5b73ffffffffffffffffffffffffffffffffffffffff16801561081b5760049060a06040918251938480927ffeaf968c0000000000000000000000000000000000000000000000000000000082525afa918215610810576000926107bf575b50805181810181811067ffffffffffffffff821117610631578252600f81526020917f6e6567617469766520616e737765720000000000000000000000000000000000838301526000841261072f5750505090565b5180927f08c379a000000000000000000000000000000000000000000000000000000000825280600483015282519283602484015260005b8481106107a8575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f836000604480968601015201168101030190fd5b818101830151868201604401528593508201610767565b909160a0823d8211610808575b816107d960a093836105f0565b8101031261080557506107eb81610660565b506107fd608060208301519201610660565b5090386106da565b80fd5b3d91506107cc565b50513d6000823e3d90fd5b50600190565b73ffffffffffffffffffffffffffffffffffffffff169081156108c0576020906024604051809481937f07a2d13a00000000000000000000000000000000000000000000000000000000835260048301525afa9081156108b457600091610886575090565b906020823d82116108ac575b8161089f602093836105f0565b8101031261080557505190565b3d9150610892565b6040513d6000823e3d90fd5b505060019056fea26469706673582212206d1afbf1b139d06c6beb42eb513c9aba924c412a2e640fa2263a47dbeb3a2fb764736f6c63430008150033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"paris","libraries":{},"metadata":{"appendCBOR":true,"bytecodeHash":"ipfs","useLiteralContent":false},"optimizer":{"enabled":true,"runs":999999},"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/","morpho-blue/=lib/morpho-blue/","openzeppelin-contracts/=lib/openzeppelin-contracts/"],"viaIR":true},"optimization_runs":999999,"sourcify_repo_url":null,"decoded_constructor_args":[["0x0000000000000000000000000000000000000000",{"internalType":"contract IERC4626","name":"vault","type":"address"}],["0xfdFD9C85aD200c506Cf9e21F1FD8dd01932FBB23",{"internalType":"contract AggregatorV3Interface","name":"baseFeed1","type":"address"}],["0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c",{"internalType":"contract AggregatorV3Interface","name":"baseFeed2","type":"address"}],["0x3E7d1eAB13ad0104d2750B8863b489D65364e32D",{"internalType":"contract AggregatorV3Interface","name":"quoteFeed1","type":"address"}],["0x0000000000000000000000000000000000000000",{"internalType":"contract AggregatorV3Interface","name":"quoteFeed2","type":"address"}],["1",{"internalType":"uint256","name":"vaultConversionSample","type":"uint256"}],["8",{"internalType":"uint256","name":"baseTokenDecimals","type":"uint256"}],["6",{"internalType":"uint256","name":"quoteTokenDecimals","type":"uint256"}]],"compiler_version":"0.8.21+commit.d9974bed","is_verified_via_verifier_alliance":true,"verified_at":"2026-02-24T10:07:40.440707Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x6101606040818152346200029d57819062000cfb8038038091620000248286620002a2565b8439610100938491810103126200029d5781516001600160a01b038116929091908383036200029d576200005b60208201620002c6565b9062000069838201620002c6565b6200007760608301620002c6565b916200008660808201620002c6565b9260a08201519460e060c084015193015198159788159862000291575b87516001600160401b03996060820191908b8311828410176200027b5762000101928b52602282527f7661756c7420636f6e76657273696f6e2073616d706c65206973206e6f74206f6020830152616e6560f01b8b830152620002db565b861598885189810191818310908311176200027b576200014f918a52601f81527f7661756c7420636f6e76657273696f6e2073616d706c65206973207a65726f0060208201528a15620002db565b6080528560a0528060c0528360e052818a5261012098858a5260240194856024116200026557620001aa620001b794620001b1620001b793620001a3620001aa620001be9b620001a3620001aa9a62000361565b9062000345565b9162000361565b62000353565b9062000353565b92604d841162000265576200024f5761014092600a0a04825251916108fd9384620003fe85396080518481816102d8015261048f015260a05184818161018e01526102b7015260c05184818160c30152610301015260e051848181610135015261033001525183818161035c015261042101525182818161025301526103850152518181816101e601526103ac0152f35b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600187149850620000a3565b600080fd5b601f909101601f19168101906001600160401b038211908210176200027b57604052565b51906001600160a01b03821682036200029d57565b15620002e45750565b6040519062461bcd60e51b82528160208060048301528251908160248401526000935b8285106200032b575050604492506000838284010152601f80199101168101030190fd5b848101820151868601604401529381019385935062000307565b919082018092116200026557565b919082039182116200026557565b6001600160a01b03168015620003f75760206004916040519283809263313ce56760e01b82525afa908115620003eb57600091620003a1575b5060ff1690565b6020813d8211620003e2575b81620003bc60209383620002a2565b81010312620003de57519060ff82168203620003db575060ff6200039a565b80fd5b5080fd5b3d9150620003ad565b6040513d6000823e3d90fd5b5060009056fe60806040818152600436101561001457600080fd5b600091823560e01c908163411557d1146104455750806356095e11146103d7578063a035b1fe14610277578063acfbd39e14610209578063ce4b5bbe146101b1578063d6c843ca14610159578063dc53858c146100eb5763f50a47181461007a57600080fd5b346100e757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e7576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b5080fd5b50346100e757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e7576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346100e757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e757602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346100e757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e757602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346100e757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e7576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346100e757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e7576020906103d061035461032b6102fc7f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610821565b6103257f000000000000000000000000000000000000000000000000000000000000000061067c565b906104b3565b6103257f000000000000000000000000000000000000000000000000000000000000000061067c565b6103a96103807f000000000000000000000000000000000000000000000000000000000000000061067c565b6103257f000000000000000000000000000000000000000000000000000000000000000061067c565b907f00000000000000000000000000000000000000000000000000000000000000006104f5565b9051908152f35b50346100e757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e7576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b8390346100e757817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e75760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b818102929181159184041417156104c657565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9091828202917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848209938380861095039480860395146105b357848311156105895782910981600003821680920460028082600302188083028203028083028203028083028203028083028203028083028203028092029003029360018380600003040190848311900302920304170290565b60046040517f227bc153000000000000000000000000000000000000000000000000000000008152fd5b5050809250156105c1570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761063157604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b519069ffffffffffffffffffff8216820361067757565b600080fd5b73ffffffffffffffffffffffffffffffffffffffff16801561081b5760049060a06040918251938480927ffeaf968c0000000000000000000000000000000000000000000000000000000082525afa918215610810576000926107bf575b50805181810181811067ffffffffffffffff821117610631578252600f81526020917f6e6567617469766520616e737765720000000000000000000000000000000000838301526000841261072f5750505090565b5180927f08c379a000000000000000000000000000000000000000000000000000000000825280600483015282519283602484015260005b8481106107a8575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f836000604480968601015201168101030190fd5b818101830151868201604401528593508201610767565b909160a0823d8211610808575b816107d960a093836105f0565b8101031261080557506107eb81610660565b506107fd608060208301519201610660565b5090386106da565b80fd5b3d91506107cc565b50513d6000823e3d90fd5b50600190565b73ffffffffffffffffffffffffffffffffffffffff169081156108c0576020906024604051809481937f07a2d13a00000000000000000000000000000000000000000000000000000000835260048301525afa9081156108b457600091610886575090565b906020823d82116108ac575b8161089f602093836105f0565b8101031261080557505190565b3d9150610892565b6040513d6000823e3d90fd5b505060019056fea26469706673582212206d1afbf1b139d06c6beb42eb513c9aba924c412a2e640fa2263a47dbeb3a2fb764736f6c634300081500330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fdfd9c85ad200c506cf9e21f1fd8dd01932fbb23000000000000000000000000f4030086522a5beea4988f8ca5b36dbc97bee88c0000000000000000000000003e7d1eab13ad0104d2750b8863b489d65364e32d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000006","name":"ChainlinkOracle","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"paris","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"lib/morpho-blue/src/interfaces/IOracle.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title IOracle\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Interface that oracles used by Morpho must implement.\n/// @dev It is the user's responsibility to select markets with safe oracles.\ninterface IOracle {\n    /// @notice Returns the price of 1 asset of collateral token quoted in 1 asset of loan token, scaled by 1e36.\n    /// @dev It corresponds to the price of 10**(collateral token decimals) assets of collateral token quoted in\n    /// 10**(loan token decimals) assets of loan token with `36 + loan token decimals - collateral token decimals`\n    /// decimals of precision.\n    function price() external view returns (uint256);\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/utils/math/Math.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    /**\n     * @dev Muldiv operation overflow.\n     */\n    error MathOverflowedMulDiv();\n\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            return a / b;\n        }\n\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0 = x * y; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            if (denominator <= prod1) {\n                revert MathOverflowedMulDiv();\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n}\n"},{"file_path":"src/interfaces/AggregatorV3Interface.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity >=0.5.0;\n\n/// @dev From\n/// https://github.com/smartcontractkit/chainlink/blob/master/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\ninterface AggregatorV3Interface {\n    function decimals() external view returns (uint8);\n\n    function description() external view returns (string memory);\n\n    function version() external view returns (uint256);\n\n    function getRoundData(uint80 _roundId)\n        external\n        view\n        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n    function latestRoundData()\n        external\n        view\n        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n}\n"},{"file_path":"src/interfaces/IChainlinkOracle.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {IERC4626} from \"./IERC4626.sol\";\nimport {AggregatorV3Interface} from \"./AggregatorV3Interface.sol\";\nimport {IOracle} from \"../../lib/morpho-blue/src/interfaces/IOracle.sol\";\n\n/// @title IChainlinkOracle\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Interface of ChainlinkOracle.\ninterface IChainlinkOracle is IOracle {\n    /// @notice Returns the address of the ERC4626 vault.\n    function VAULT() external view returns (IERC4626);\n\n    /// @notice Returns the vault conversion sample.\n    function VAULT_CONVERSION_SAMPLE() external view returns (uint256);\n\n    /// @notice Returns the address of the first Chainlink base feed.\n    function BASE_FEED_1() external view returns (AggregatorV3Interface);\n\n    /// @notice Returns the address of the second Chainlink base feed.\n    function BASE_FEED_2() external view returns (AggregatorV3Interface);\n\n    /// @notice Returns the address of the first Chainlink quote feed.\n    function QUOTE_FEED_1() external view returns (AggregatorV3Interface);\n\n    /// @notice Returns the address of the second Chainlink quote feed.\n    function QUOTE_FEED_2() external view returns (AggregatorV3Interface);\n\n    /// @notice Returns the price scale factor, calculated at contract creation.\n    function SCALE_FACTOR() external view returns (uint256);\n}\n"},{"file_path":"src/interfaces/IERC4626.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\ninterface IERC4626 {\n    function convertToAssets(uint256) external view returns (uint256);\n}\n"},{"file_path":"src/libraries/ChainlinkDataFeedLib.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {AggregatorV3Interface} from \"../interfaces/AggregatorV3Interface.sol\";\n\nimport {ErrorsLib} from \"./ErrorsLib.sol\";\n\n/// @title ChainlinkDataFeedLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Library exposing functions to interact with a Chainlink-compliant feed.\nlibrary ChainlinkDataFeedLib {\n    /// @dev Performs safety checks and returns the latest price of a `feed`.\n    /// @dev When `feed` is the address zero, returns 1.\n    /// @dev Notes on safety checks:\n    /// - L2s are not supported.\n    /// - Staleness is not checked because it's assumed that the Chainlink feed keeps its promises on this.\n    /// - The price is not checked to be in the min/max bounds because it's assumed that the Chainlink feed keeps its\n    /// promises on this.\n    function getPrice(AggregatorV3Interface feed) internal view returns (uint256) {\n        if (address(feed) == address(0)) return 1;\n\n        (, int256 answer,,,) = feed.latestRoundData();\n        require(answer >= 0, ErrorsLib.NEGATIVE_ANSWER);\n\n        return uint256(answer);\n    }\n\n    /// @dev Returns the number of decimals of a `feed`.\n    /// @dev When `feed` is the address zero, returns 0.\n    function getDecimals(AggregatorV3Interface feed) internal view returns (uint256) {\n        if (address(feed) == address(0)) return 0;\n\n        return feed.decimals();\n    }\n}\n"},{"file_path":"src/libraries/ErrorsLib.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\n/// @title ErrorsLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Library exposing error messages.\nlibrary ErrorsLib {\n    /// @notice Thrown when the answer returned by a Chainlink feed is negative.\n    string constant NEGATIVE_ANSWER = \"negative answer\";\n\n    /// @notice Thrown when the vault conversion sample is 0.\n    string constant VAULT_CONVERSION_SAMPLE_IS_ZERO = \"vault conversion sample is zero\";\n\n    /// @notice Thrown when the vault conversion sample is not 1 while vault = address(0).\n    string constant VAULT_CONVERSION_SAMPLE_IS_NOT_ONE = \"vault conversion sample is not one\";\n}\n"},{"file_path":"src/libraries/VaultLib.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {IERC4626} from \"../interfaces/IERC4626.sol\";\n\n/// @title VaultLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Library exposing functions to price shares of an ERC4626 vault.\nlibrary VaultLib {\n    /// @dev Converts `shares` into the corresponding assets on the `vault`.\n    /// @dev When `vault` is the address zero, returns 1.\n    function getAssets(IERC4626 vault, uint256 shares) internal view returns (uint256) {\n        if (address(vault) == address(0)) return 1;\n\n        return vault.convertToAssets(shares);\n    }\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"contract IERC4626","name":"vault","type":"address"},{"internalType":"contract AggregatorV3Interface","name":"baseFeed1","type":"address"},{"internalType":"contract AggregatorV3Interface","name":"baseFeed2","type":"address"},{"internalType":"contract AggregatorV3Interface","name":"quoteFeed1","type":"address"},{"internalType":"contract AggregatorV3Interface","name":"quoteFeed2","type":"address"},{"internalType":"uint256","name":"vaultConversionSample","type":"uint256"},{"internalType":"uint256","name":"baseTokenDecimals","type":"uint256"},{"internalType":"uint256","name":"quoteTokenDecimals","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"MathOverflowedMulDiv","type":"error"},{"inputs":[],"name":"BASE_FEED_1","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BASE_FEED_2","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"QUOTE_FEED_1","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"QUOTE_FEED_2","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SCALE_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VAULT","outputs":[{"internalType":"contract IERC4626","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VAULT_CONVERSION_SAMPLE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fdfd9c85ad200c506cf9e21f1fd8dd01932fbb23000000000000000000000000f4030086522a5beea4988f8ca5b36dbc97bee88c0000000000000000000000003e7d1eab13ad0104d2750b8863b489d65364e32d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000006"}