{"file_path":"contracts/WstETHPriceFeed.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport \"./IPriceFeed.sol\";\nimport \"./IWstETH.sol\";\n\n/**\n * @title wstETH price feed\n * @notice A custom price feed that calculates the price for wstETH / ETH\n * @author Compound\n */\ncontract WstETHPriceFeed is IPriceFeed {\n    /** Custom errors **/\n    error BadDecimals();\n    error InvalidInt256();\n\n    /// @notice Version of the price feed\n    uint public constant override version = 1;\n\n    /// @notice Description of the price feed\n    string public constant override description = \"Custom price feed for wstETH / ETH\";\n\n    /// @notice Number of decimals for returned prices\n    uint8 public immutable override decimals;\n\n    /// @notice Chainlink stETH / ETH price feed\n    address public immutable stETHtoETHPriceFeed;\n\n    /// @notice Number of decimals for the stETH / ETH price feed\n    uint public immutable stETHToETHPriceFeedDecimals;\n\n    /// @notice WstETH contract address\n    address public immutable wstETH;\n\n    /// @notice Scale for WstETH contract\n    int public immutable wstETHScale;\n\n    constructor(address stETHtoETHPriceFeed_, address wstETH_, uint8 decimals_) {\n        stETHtoETHPriceFeed = stETHtoETHPriceFeed_;\n        stETHToETHPriceFeedDecimals = AggregatorV3Interface(stETHtoETHPriceFeed_).decimals();\n        wstETH = wstETH_;\n        // Note: Safe to convert directly to an int256 because wstETH.decimals == 18\n        wstETHScale = int256(10 ** IWstETH(wstETH).decimals());\n\n        // Note: stETH / ETH price feed has 18 decimals so `decimals_` should always be less than or equals to that\n        if (decimals_ > stETHToETHPriceFeedDecimals) revert BadDecimals();\n        decimals = decimals_;\n    }\n\n    function signed256(uint256 n) internal pure returns (int256) {\n        if (n > uint256(type(int256).max)) revert InvalidInt256();\n        return int256(n);\n    }\n\n    /**\n     * @notice WstETH price for the latest round\n     * @return roundId Round id from the stETH price feed\n     * @return answer Latest price for wstETH / USD\n     * @return startedAt Timestamp when the round was started; passed on from stETH price feed\n     * @return updatedAt Timestamp when the round was last updated; passed on from stETH price feed\n     * @return answeredInRound Round id in which the answer was computed; passed on from stETH price feed\n     **/\n    function latestRoundData() override external view returns (\n        uint80 roundId,\n        int256 answer,\n        uint256 startedAt,\n        uint256 updatedAt,\n        uint80 answeredInRound\n    ) {\n        (uint80 roundId_, int256 stETHPrice, uint256 startedAt_, uint256 updatedAt_, uint80 answeredInRound_) = AggregatorV3Interface(stETHtoETHPriceFeed).latestRoundData();\n        uint256 tokensPerStEth = IWstETH(wstETH).tokensPerStEth();\n        int256 price = stETHPrice * wstETHScale / signed256(tokensPerStEth);\n        // Note: The stETH price feed should always have an equal or larger amount of decimals than this price feed (enforced by validation in constructor)\n        int256 scaledPrice = price / int256(10 ** (stETHToETHPriceFeedDecimals - decimals));\n        return (roundId_, scaledPrice, startedAt_, updatedAt_, answeredInRound_);\n    }\n}","deployed_bytecode":"0x608060408181526004918236101561001657600080fd5b600090813560e01c90816317f098ca146105245750806322c2b36c146104e9578063313ce567146104ab5780634aa07e641461046757806354fd4d501461044b5780637284e416146103a0578063ed1a68d1146103585763feaf968c1461007c57600080fd5b346103555780600319360112610355578151633fabe5a360e21b81526001600160a01b039060a08186817f00000000000000000000000086392dc19c0b719886221c78ab11eb8cf5c5281286165afa91821561034b578380878293839584976102e6575b506020908951928380926312aed41960e31b82527f0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0165afa9081156102dc5783916102a7575b507f0000000000000000000000000000000000000000000000000de0b6b3a76400006001600160ff1b0384841385831381811684840487111661028057600160ff1b918785129190821687840586121661029357848888129305871290831616610280571682820585121661026d57821161025d576101a592026105b0565b907f000000000000000000000000000000000000000000000000000000000000000860ff167f000000000000000000000000000000000000000000000000000000000000001281811061024a570390604d8211610237575060a097509061020f91600a0a906105b0565b85516001600160501b0395861681526020810191909152948501526060840152166080820152f35b634e487b7160e01b815260118952602490fd5b634e487b7160e01b835260118a52602483fd5b885163e7e828ad60e01b81528a90fd5b634e487b7160e01b855260118b52602485fd5b634e487b7160e01b875260118d52602487fd5b50634e487b7160e01b875260118d52602487fd5b90506020813d82116102d4575b816102c16020938361055e565b810103126102d0575138610126565b8280fd5b3d91506102b4565b88513d85823e3d90fd5b95509550505093505060a0813d8211610343575b8161030760a0938361055e565b810103126102d05761031881610597565b9060208101519385820151876020610337608060608701519601610597565b959792949596906100e0565b3d91506102fa565b84513d85823e3d90fd5b80fd5b50903461039c578160031936011261039c57517f00000000000000000000000086392dc19c0b719886221c78ab11eb8cf5c528126001600160a01b03168152602090f35b5080fd5b50903461039c578160031936011261039c5780516103bf60608261055e565b602281526020907f437573746f6d207072696365206665656420666f7220777374455448202f204582820152610a8960f31b838201528251938285938452825192838286015282915b8483106104335750508210610427575b50601f01601f19168101030190f35b83828401015284610418565b81830181015188840188015287955091820191610408565b50903461039c578160031936011261039c576020905160018152f35b50903461039c578160031936011261039c57517f0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca06001600160a01b03168152602090f35b50903461039c578160031936011261039c576020905160ff7f0000000000000000000000000000000000000000000000000000000000000008168152f35b50903461039c578160031936011261039c57602090517f00000000000000000000000000000000000000000000000000000000000000128152f35b90503461039c578160031936011261039c576020907f0000000000000000000000000000000000000000000000000de0b6b3a76400008152f35b601f909101601f19168101906001600160401b0382119082101761058157604052565b634e487b7160e01b600052604160045260246000fd5b51906001600160501b03821682036105ab57565b600080fd5b81156105e157600160ff1b81146000198314166105cb570590565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fdfea2646970667358221220b5b758bb8e82efba778ccf5fe66d27c2d2ed7a1e53dec147b6cedc5cd496875a64736f6c634300080f0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"libraries":{},"optimizer":{"details":{"yulDetails":{"optimizerSteps":"dhfoDgvulfnTUtnIf [xa[r]scLM cCTUtTOntnfDIul Lcul Vcul [j] Tpeul xa[rul] xa[r]cL gvif CTUca[r]LsTOtfDnca[r]Iulc] jmul[jul] VcTOcul jmul"}},"enabled":true,"runs":1},"viaIR":true},"optimization_runs":1,"sourcify_repo_url":null,"decoded_constructor_args":[["0x86392dC19c0b719886221c78AB11eb8Cf5c52812",{"internalType":"address","name":"stETHtoETHPriceFeed_","type":"address"}],["0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0",{"internalType":"address","name":"wstETH_","type":"address"}],["8",{"internalType":"uint8","name":"decimals_","type":"uint8"}]],"compiler_version":"0.8.15+commit.e14f2714","is_verified_via_verifier_alliance":true,"verified_at":"2024-02-25T22:08:53.439689Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x6101206040818152346101e257606082610870803803809161002182856101e7565b8339810103126101e25761003482610220565b602061004c83610045838701610220565b9501610234565b938260a052835163313ce56760e01b90818152838160048160018060a01b038099165afa9081156101d7579084939291600091610198575b509060ff6004921660c0528260e052865195869384928352165afa90811561018d57600091610155575b5060ff91501691604d831161013f5761010092600a0a835260c05160ff82161161012e576080525161062d918261024383396080518281816101a801526104c5015260a05182818160a8015261036d015260c0518281816101cc0152610501015260e05182818160f6015261047c015251818181610129015261053b0152f35b8151630456c65960e51b8152600490fd5b634e487b7160e01b600052601160045260246000fd5b82813d8311610186575b61016981836101e7565b81010312610183575061017d60ff91610234565b386100ae565b80fd5b503d61015f565b83513d6000823e3d90fd5b91929382813d83116101d0575b6101af81836101e7565b81010312610183575083929160ff6101c8600493610234565b919250610084565b503d6101a5565b86513d6000823e3d90fd5b600080fd5b601f909101601f19168101906001600160401b0382119082101761020a57604052565b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036101e257565b519060ff821682036101e25756fe608060408181526004918236101561001657600080fd5b600090813560e01c90816317f098ca146105245750806322c2b36c146104e9578063313ce567146104ab5780634aa07e641461046757806354fd4d501461044b5780637284e416146103a0578063ed1a68d1146103585763feaf968c1461007c57600080fd5b346103555780600319360112610355578151633fabe5a360e21b81526001600160a01b039060a08186817f000000000000000000000000000000000000000000000000000000000000000086165afa91821561034b578380878293839584976102e6575b506020908951928380926312aed41960e31b82527f0000000000000000000000000000000000000000000000000000000000000000165afa9081156102dc5783916102a7575b507f00000000000000000000000000000000000000000000000000000000000000006001600160ff1b0384841385831381811684840487111661028057600160ff1b918785129190821687840586121661029357848888129305871290831616610280571682820585121661026d57821161025d576101a592026105b0565b907f000000000000000000000000000000000000000000000000000000000000000060ff167f000000000000000000000000000000000000000000000000000000000000000081811061024a570390604d8211610237575060a097509061020f91600a0a906105b0565b85516001600160501b0395861681526020810191909152948501526060840152166080820152f35b634e487b7160e01b815260118952602490fd5b634e487b7160e01b835260118a52602483fd5b885163e7e828ad60e01b81528a90fd5b634e487b7160e01b855260118b52602485fd5b634e487b7160e01b875260118d52602487fd5b50634e487b7160e01b875260118d52602487fd5b90506020813d82116102d4575b816102c16020938361055e565b810103126102d0575138610126565b8280fd5b3d91506102b4565b88513d85823e3d90fd5b95509550505093505060a0813d8211610343575b8161030760a0938361055e565b810103126102d05761031881610597565b9060208101519385820151876020610337608060608701519601610597565b959792949596906100e0565b3d91506102fa565b84513d85823e3d90fd5b80fd5b50903461039c578160031936011261039c57517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5080fd5b50903461039c578160031936011261039c5780516103bf60608261055e565b602281526020907f437573746f6d207072696365206665656420666f7220777374455448202f204582820152610a8960f31b838201528251938285938452825192838286015282915b8483106104335750508210610427575b50601f01601f19168101030190f35b83828401015284610418565b81830181015188840188015287955091820191610408565b50903461039c578160031936011261039c576020905160018152f35b50903461039c578160031936011261039c57517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50903461039c578160031936011261039c576020905160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50903461039c578160031936011261039c57602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b90503461039c578160031936011261039c576020907f00000000000000000000000000000000000000000000000000000000000000008152f35b601f909101601f19168101906001600160401b0382119082101761058157604052565b634e487b7160e01b600052604160045260246000fd5b51906001600160501b03821682036105ab57565b600080fd5b81156105e157600160ff1b81146000198314166105cb570590565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fdfea2646970667358221220b5b758bb8e82efba778ccf5fe66d27c2d2ed7a1e53dec147b6cedc5cd496875a64736f6c634300080f003300000000000000000000000086392dc19c0b719886221c78ab11eb8cf5c528120000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca00000000000000000000000000000000000000000000000000000000000000008","name":"WstETHPriceFeed","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"default","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"contracts/ERC20.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/**\n * @title ERC 20 Token Standard Interface\n *  https://eips.ethereum.org/EIPS/eip-20\n */\ninterface ERC20 {\n    function name() external view returns (string memory);\n    function symbol() external view returns (string memory);\n    function decimals() external view returns (uint8);\n\n    /**\n      * @notice Get the total number of tokens in circulation\n      * @return The supply of tokens\n      */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @notice Gets the balance of the specified address\n     * @param owner The address from which the balance will be retrieved\n     * @return The balance\n     */\n    function balanceOf(address owner) external view returns (uint256);\n\n    /**\n      * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n      * @param dst The address of the destination account\n      * @param amount The number of tokens to transfer\n      * @return Whether or not the transfer succeeded\n      */\n    function transfer(address dst, uint256 amount) external returns (bool);\n\n    /**\n      * @notice Transfer `amount` tokens from `src` to `dst`\n      * @param src The address of the source account\n      * @param dst The address of the destination account\n      * @param amount The number of tokens to transfer\n      * @return Whether or not the transfer succeeded\n      */\n    function transferFrom(address src, address dst, uint256 amount) external returns (bool);\n\n    /**\n      * @notice Approve `spender` to transfer up to `amount` from `src`\n      * @dev This will overwrite the approval amount for `spender`\n      *  and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n      * @param spender The address of the account which may transfer tokens\n      * @param amount The number of tokens that are approved (-1 means infinite)\n      * @return Whether or not the approval succeeded\n      */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n      * @notice Get the current allowance from `owner` for `spender`\n      * @param owner The address of the account which owns the tokens to be spent\n      * @param spender The address of the account which may transfer tokens\n      * @return The number of tokens allowed to be spent (-1 means infinite)\n      */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    event Transfer(address indexed from, address indexed to, uint256 amount);\n    event Approval(address indexed owner, address indexed spender, uint256 amount);\n}\n"},{"file_path":"contracts/IPriceFeed.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/**\n * @dev Interface for price feeds used by Comet\n * Note This is Chainlink's AggregatorV3Interface, but without the `getRoundData` function.\n */\ninterface IPriceFeed {\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 latestRoundData()\n    external\n    view\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    );\n}"},{"file_path":"contracts/IWstETH.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./ERC20.sol\";\n\n/**\n * @dev Interface for interacting with WstETH contract\n * Note Not a comprehensive interface\n */\ninterface IWstETH is ERC20 {\n    function stETH() external returns (address);\n\n    function wrap(uint256 _stETHAmount) external returns (uint256);\n    function unwrap(uint256 _wstETHAmount) external returns (uint256);\n\n    function receive() external payable;\n\n    function getWstETHByStETH(uint256 _stETHAmount) external view returns (uint256);\n    function getStETHByWstETH(uint256 _wstETHAmount) external view returns (uint256);\n\n    function stEthPerToken() external view returns (uint256);\n    function tokensPerStEth() external view returns (uint256);\n}"},{"file_path":"contracts/vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\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  // getRoundData and latestRoundData should both raise \"No data present\"\n  // if they do not have data to report, instead of returning unset values\n  // which could be misinterpreted as actual reported values.\n  function getRoundData(uint80 _roundId)\n    external\n    view\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    );\n\n  function latestRoundData()\n    external\n    view\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    );\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"stETHtoETHPriceFeed_","type":"address"},{"internalType":"address","name":"wstETH_","type":"address"},{"internalType":"uint8","name":"decimals_","type":"uint8"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BadDecimals","type":"error"},{"inputs":[],"name":"InvalidInt256","type":"error"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"description","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestRoundData","outputs":[{"internalType":"uint80","name":"roundId","type":"uint80"},{"internalType":"int256","name":"answer","type":"int256"},{"internalType":"uint256","name":"startedAt","type":"uint256"},{"internalType":"uint256","name":"updatedAt","type":"uint256"},{"internalType":"uint80","name":"answeredInRound","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stETHToETHPriceFeedDecimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stETHtoETHPriceFeed","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wstETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wstETHScale","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0x00000000000000000000000086392dc19c0b719886221c78ab11eb8cf5c528120000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca00000000000000000000000000000000000000000000000000000000000000008"}