{"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":"0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063ce4b5bbe1161005b578063ce4b5bbe14610135578063d6c843ca1461015c578063dc53858c14610183578063f50a4718146101aa57600080fd5b8063411557d11461008d57806356095e11146100d1578063a035b1fe146100f8578063acfbd39e1461010e575b600080fd5b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b6100b47f000000000000000000000000986b5e1e1755e3c2440e960477f25201b0a8bbd481565b6101006101d1565b6040519081526020016100c8565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6101007f000000000000000000000000000000000001ed09bead87c0378d8e640000000081565b6101007f000000000000000000000000000000000000000000000000000000000000000181565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6100b47f0000000000000000000000004f67e4d9bd67efa28236013288737d39aef48e7981565b60006103376102087f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661033c565b61023a7f0000000000000000000000004f67e4d9bd67efa28236013288737d39aef48e796001600160a01b031661033c565b61028d6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000001610419565b6102979190610568565b6102a19190610568565b6102d37f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661033c565b6103057f000000000000000000000000986b5e1e1755e3c2440e960477f25201b0a8bbd46001600160a01b031661033c565b61030f9190610568565b7f000000000000000000000000000000000001ed09bead87c0378d8e640000000091906104a3565b905090565b60006001600160a01b03821661035457506001919050565b6000826001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610394573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b891906105ac565b50505091505060008112156040518060400160405280600f81526020016e3732b3b0ba34bb329030b739bbb2b960891b815250906104125760405162461bcd60e51b815260040161040991906105fc565b60405180910390fd5b5092915050565b60006001600160a01b0383166104315750600161049d565b6040516303d1689d60e11b8152600481018390526001600160a01b038416906307a2d13a90602401602060405180830381865afa158015610476573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049a919061064a565b90505b92915050565b60008383028160001985870982811083820303915050806000036104da578382816104d0576104d0610663565b0492505050610561565b8084116104fa5760405163227bc15360e01b815260040160405180910390fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b808202811582820484141761049d57634e487b7160e01b600052601160045260246000fd5b805169ffffffffffffffffffff811681146105a757600080fd5b919050565b600080600080600060a086880312156105c457600080fd5b6105cd8661058d565b94506020860151935060408601519250606086015191506105f06080870161058d565b90509295509295909350565b600060208083528351808285015260005b818110156106295785810183015185820160400152820161060d565b506000604082860101526040601f19601f8301168501019250505092915050565b60006020828403121561065c57600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fdfea2646970667358221220550e49662f7bf52eb0ae184f1a0e163ddb179b44eff62aa470bfbeb2a5fb75d164736f6c63430008150033","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":200},"outputSelection":{"*":{"":["*"],"*":["*"]}},"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/"]},"optimization_runs":200,"sourcify_repo_url":null,"decoded_constructor_args":[["0x0000000000000000000000000000000000000000",{"internalType":"contract IERC4626","name":"vault","type":"address"}],["0x4F67e4d9BD67eFa28236013288737D39AeF48e79",{"internalType":"contract AggregatorV3Interface","name":"baseFeed1","type":"address"}],["0x0000000000000000000000000000000000000000",{"internalType":"contract AggregatorV3Interface","name":"baseFeed2","type":"address"}],["0x986b5E1e1755e3C2440e960477f25201B0a8bbD4",{"internalType":"contract AggregatorV3Interface","name":"quoteFeed1","type":"address"}],["0x0000000000000000000000000000000000000000",{"internalType":"contract AggregatorV3Interface","name":"quoteFeed2","type":"address"}],["1",{"internalType":"uint256","name":"vaultConversionSample","type":"uint256"}],["18",{"internalType":"uint256","name":"baseTokenDecimals","type":"uint256"}],["6",{"internalType":"uint256","name":"quoteTokenDecimals","type":"uint256"}]],"compiler_version":"v0.8.21+commit.d9974bed","is_verified_via_verifier_alliance":false,"verified_at":"2026-01-26T14:42:58.913683Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x6101606040523480156200001257600080fd5b5060405162000c5e38038062000c5e833981016040819052620000359162000276565b6001600160a01b0388161515806200004d5750826001145b60405180606001604052806022815260200162000c3c6022913990620000915760405162461bcd60e51b815260040162000088919062000311565b60405180910390fd5b5060408051808201909152601f81527f7661756c7420636f6e76657273696f6e2073616d706c65206973207a65726f00602082015283620000e75760405162461bcd60e51b815260040162000088919062000311565b506001600160a01b0380891660805260a084905287811660c05286811660e0819052868216610100529085166101205283906200012490620001d6565b620001386001600160a01b038a16620001d6565b846200014d6001600160a01b038916620001d6565b620001616001600160a01b038b16620001d6565b6200016e87602462000377565b6200017a919062000377565b62000186919062000377565b62000192919062000393565b6200019e919062000393565b620001aa919062000393565b620001b790600a620004a6565b620001c39190620004bb565b6101405250620005039650505050505050565b60006001600160a01b038216620001ef57506000919050565b816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200022e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002549190620004de565b60ff1692915050565b6001600160a01b03811681146200027357600080fd5b50565b600080600080600080600080610100898b0312156200029457600080fd5b8851620002a1816200025d565b60208a0151909850620002b4816200025d565b60408a0151909750620002c7816200025d565b60608a0151909650620002da816200025d565b60808a0151909550620002ed816200025d565b60a08a015160c08b015160e0909b0151999c989b5096999598909790945092505050565b600060208083528351808285015260005b81811015620003405785810183015185820160400152820162000322565b506000604082860101526040601f19601f8301168501019250505092915050565b634e487b7160e01b600052601160045260246000fd5b808201808211156200038d576200038d62000361565b92915050565b818103818111156200038d576200038d62000361565b600181815b80851115620003ea578160001904821115620003ce57620003ce62000361565b80851615620003dc57918102915b93841c9390800290620003ae565b509250929050565b60008262000403575060016200038d565b8162000412575060006200038d565b81600181146200042b5760028114620004365762000456565b60019150506200038d565b60ff8411156200044a576200044a62000361565b50506001821b6200038d565b5060208310610133831016604e8410600b84101617156200047b575081810a6200038d565b620004878383620003a9565b80600019048211156200049e576200049e62000361565b029392505050565b6000620004b48383620003f2565b9392505050565b600082620004d957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215620004f157600080fd5b815160ff81168114620004b457600080fd5b60805160a05160c05160e0516101005161012051610140516106af6200058d6000396000818161013a015261031101526000818161011301526102a601526000818160d601526102d801526000818161018801526101db0152600081816101af015261020d01526000818161016101526102690152600081816092015261024701526106af6000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063ce4b5bbe1161005b578063ce4b5bbe14610135578063d6c843ca1461015c578063dc53858c14610183578063f50a4718146101aa57600080fd5b8063411557d11461008d57806356095e11146100d1578063a035b1fe146100f8578063acfbd39e1461010e575b600080fd5b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6101006101d1565b6040519081526020016100c8565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6101007f000000000000000000000000000000000000000000000000000000000000000081565b6101007f000000000000000000000000000000000000000000000000000000000000000081565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b60006103376102087f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661033c565b61023a7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661033c565b61028d6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000610419565b6102979190610568565b6102a19190610568565b6102d37f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661033c565b6103057f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661033c565b61030f9190610568565b7f000000000000000000000000000000000000000000000000000000000000000091906104a3565b905090565b60006001600160a01b03821661035457506001919050565b6000826001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610394573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b891906105ac565b50505091505060008112156040518060400160405280600f81526020016e3732b3b0ba34bb329030b739bbb2b960891b815250906104125760405162461bcd60e51b815260040161040991906105fc565b60405180910390fd5b5092915050565b60006001600160a01b0383166104315750600161049d565b6040516303d1689d60e11b8152600481018390526001600160a01b038416906307a2d13a90602401602060405180830381865afa158015610476573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049a919061064a565b90505b92915050565b60008383028160001985870982811083820303915050806000036104da578382816104d0576104d0610663565b0492505050610561565b8084116104fa5760405163227bc15360e01b815260040160405180910390fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b808202811582820484141761049d57634e487b7160e01b600052601160045260246000fd5b805169ffffffffffffffffffff811681146105a757600080fd5b919050565b600080600080600060a086880312156105c457600080fd5b6105cd8661058d565b94506020860151935060408601519250606086015191506105f06080870161058d565b90509295509295909350565b600060208083528351808285015260005b818110156106295785810183015185820160400152820161060d565b506000604082860101526040601f19601f8301168501019250505092915050565b60006020828403121561065c57600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fdfea2646970667358221220550e49662f7bf52eb0ae184f1a0e163ddb179b44eff62aa470bfbeb2a5fb75d164736f6c634300081500337661756c7420636f6e76657273696f6e2073616d706c65206973206e6f74206f6e6500000000000000000000000000000000000000000000000000000000000000000000000000000000000000004f67e4d9bd67efa28236013288737d39aef48e790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000986b5e1e1755e3c2440e960477f25201b0a8bbd40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000006","name":"ChainlinkOracle","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":false,"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":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000004f67e4d9bd67efa28236013288737d39aef48e790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000986b5e1e1755e3c2440e960477f25201b0a8bbd40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000006"}