├── .czrc ├── .editorconfig ├── .env.example ├── .eslintignore ├── .eslintrc ├── .eslinttsconfigrc ├── .github ├── pull_request_template.md └── workflows │ ├── cd.yaml │ └── ci.yml ├── .gitignore ├── .husky └── commit-msg ├── .lintstagedrc ├── .npmignore ├── .prettierignore ├── .prettierrc.yaml ├── .releaserc ├── .solcover.js ├── .solhint.json ├── .solhintignore ├── .yarn ├── plugins │ └── @yarnpkg │ │ └── plugin-interactive-tools.cjs └── releases │ └── yarn-3.2.0.cjs ├── .yarnrc.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── audits ├── 013_oracles_peckshield_20230424.pdf ├── 016_oracles_hacken_20230426.pdf ├── 024_oracles_certik_20230522.pdf ├── 026_oracles_openzeppelin_20230606.pdf ├── 043_getPrice_certik_20230717.pdf ├── 045_getPrice_peckshield_20230712.pdf ├── 090_wstETHOracle_certik_20240126.pdf ├── 093_wstETHOracle_quantstamp_20240220.pdf ├── 097_twap_hashex_20240201.pdf ├── 098_correlated_token_oracles_certik_20240412.pdf ├── 100_correlated_token_oracles_quantstamp_20240412.pdf ├── 101_correlated_token_oracles_fairyproof_20240328.pdf ├── 110_sfrxETHOracle_certik_20240517.pdf ├── 111_sfrxETHOracle_quantstamp_20240530.pdf ├── 116_WeETHAccountantOracle_certik_20240823.pdf ├── 119_pendleOracleUpdate_certik_20241226.pdf ├── 123_erc4626Oracle_certik_20250206.pdf ├── 124_oracles_certik_20250225.pdf └── 128_AsBNBOracle_certik_20250320.pdf ├── commitlint.config.js ├── contracts ├── ReferenceOracle.sol ├── ResilientOracle.sol ├── interfaces │ ├── FeedRegistryInterface.sol │ ├── IAccountant.sol │ ├── IAnkrBNB.sol │ ├── IAsBNB.sol │ ├── IAsBNBMinter.sol │ ├── IERC4626.sol │ ├── IEtherFiLiquidityPool.sol │ ├── IPStakePool.sol │ ├── IPendlePtOracle.sol │ ├── ISFrax.sol │ ├── ISfrxEthFraxOracle.sol │ ├── IStETH.sol │ ├── IStaderStakeManager.sol │ ├── ISynclubStakeManager.sol │ ├── IWBETH.sol │ ├── IZkETH.sol │ ├── OracleInterface.sol │ ├── PublicResolverInterface.sol │ ├── PythInterface.sol │ ├── SIDRegistryInterface.sol │ └── VBep20Interface.sol ├── oracles │ ├── AnkrBNBOracle.sol │ ├── AsBNBOracle.sol │ ├── BNBxOracle.sol │ ├── BinanceOracle.sol │ ├── BoundValidator.sol │ ├── ChainlinkOracle.sol │ ├── ERC4626Oracle.sol │ ├── EtherfiAccountantOracle.sol │ ├── OneJumpOracle.sol │ ├── PendleOracle.sol │ ├── PythOracle.sol │ ├── SFraxOracle.sol │ ├── SFrxETHOracle.sol │ ├── SequencerChainlinkOracle.sol │ ├── SlisBNBOracle.sol │ ├── StkBNBOracle.sol │ ├── WBETHOracle.sol │ ├── WeETHAccountantOracle.sol │ ├── WeETHOracle.sol │ ├── WstETHOracle.sol │ ├── WstETHOracleV2.sol │ ├── ZkETHOracle.sol │ ├── common │ │ └── CorrelatedTokenOracle.sol │ └── mocks │ │ ├── MockAccountant.sol │ │ ├── MockBinanceFeedRegistry.sol │ │ ├── MockBinanceOracle.sol │ │ ├── MockChainlinkOracle.sol │ │ ├── MockPendlePtOracle.sol │ │ ├── MockPythOracle.sol │ │ └── MockSFrxEthFraxOracle.sol └── test │ ├── BEP20Harness.sol │ ├── MockAnkrBNB.sol │ ├── MockAsBNB.sol │ ├── MockAsBNBMinter.sol │ ├── MockEtherFiLiquidityPool.sol │ ├── MockPyth.sol │ ├── MockSFrax.sol │ ├── MockSimpleOracle.sol │ ├── MockV3Aggregator.sol │ ├── MockWBETH.sol │ ├── PancakePairHarness.sol │ └── VBEP20Harness.sol ├── deploy ├── 1-deploy-oracles.ts ├── 10-deploy-rsETH-oracles.ts ├── 11-dependencies-sfrxeth-oracle.ts ├── 11-deploy-sfrxeth-oracle.ts ├── 11-setup-sfrxeth-oracle.ts ├── 12-deploy-ezETH-oracles.ts ├── 13-dependencies-weETHs-oracle.ts ├── 13-deploy-weETHs-oracle.ts ├── 13-deploy-wstETH-weETH-oracles.ts ├── 14-dependencies-eBTC-oracle.ts ├── 14-deploy-ERC4626Oracle.ts ├── 14-deploy-eBTC-oracle.ts ├── 14-deploy-pufETH-oracle.ts ├── 15-deploy-lbtc-oracle.ts ├── 16-deploy-SolvBTC.BBN-pendle-oracles.ts ├── 17-deploy-wUSDM-oracle.ts ├── 18-deploy-sUSDC-oracle.ts ├── 18-deploy-wsuperOETHb-oracle.ts ├── 19-deploy-yearn-oracles.ts ├── 2-deploy-binance-oracle.ts ├── 2-deploy-pyth-oracle.ts ├── 2-deploy-redstone-oracle.ts ├── 2-deploy-reference-oracle.ts ├── 20-deploy-clisBNB-pendle-oracle.ts ├── 20-deploy-wstETH-one-jump-oracle.ts ├── 20-deploy-zkETH-oracle.ts ├── 21-deploy-asBNB-oracle.ts ├── 22-deploy-sUSDe-pendle-oracles.ts ├── 23-deploy-xSolvBTC.ts ├── 3-configure-feeds.ts ├── 3-resilient-oracle-imp-update.ts ├── 4-vip-based-configuration.ts ├── 5-dependencies-bnb-lst-oracles.ts ├── 5-deploy-bnb-lst-oracles.ts ├── 6-deploy-wstETH-oracle.ts ├── 7-dependencies-pendle-oracle.ts ├── 7-deploy-pendle-oracle.ts ├── 8-dependencies-weETH-oracle.ts ├── 8-deploy-weETH-oracle.ts ├── 9-dependencies-sfrax-oracle.ts └── 9-deploy-sfrax-oracle.ts ├── deployments ├── .gitkeep ├── arbitrumone.json ├── arbitrumone │ ├── .chainId │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── RedStoneOracle.json │ ├── RedStoneOracle_Implementation.json │ ├── RedStoneOracle_Proxy.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ ├── SequencerChainlinkOracle.json │ ├── SequencerChainlinkOracle_Implementation.json │ ├── SequencerChainlinkOracle_Proxy.json │ ├── solcInputs │ │ ├── 0e89febeebc7444140de8e67c9067d2c.json │ │ ├── 49d9f4b37cd7173493a35d973c18f6ba.json │ │ └── d185d116dd1c48d32d2e3ff045d30d4c.json │ ├── weETHOneJumpChainlinkOracle.json │ ├── weETHOneJumpChainlinkOracle_Implementation.json │ ├── weETHOneJumpChainlinkOracle_Proxy.json │ ├── wstETHOneJumpChainlinkOracle.json │ ├── wstETHOneJumpChainlinkOracle_Implementation.json │ └── wstETHOneJumpChainlinkOracle_Proxy.json ├── arbitrumone_addresses.json ├── arbitrumsepolia.json ├── arbitrumsepolia │ ├── .chainId │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── ChainlinkOracle.json │ ├── ChainlinkOracle_Implementation.json │ ├── ChainlinkOracle_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── RedStoneOracle.json │ ├── RedStoneOracle_Implementation.json │ ├── RedStoneOracle_Proxy.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ ├── solcInputs │ │ ├── 0e89febeebc7444140de8e67c9067d2c.json │ │ ├── 5fd8ffb8ca29be894659558e2d50904b.json │ │ ├── b7419dfa848dc761e42395fa238da123.json │ │ ├── c9234768a0e90787a3e044ab631ca909.json │ │ └── d185d116dd1c48d32d2e3ff045d30d4c.json │ ├── weETHOneJumpChainlinkOracle.json │ ├── weETHOneJumpChainlinkOracle_Implementation.json │ ├── weETHOneJumpChainlinkOracle_Proxy.json │ ├── wstETHOneJumpChainlinkOracle.json │ ├── wstETHOneJumpChainlinkOracle_Implementation.json │ └── wstETHOneJumpChainlinkOracle_Proxy.json ├── arbitrumsepolia_addresses.json ├── basemainnet.json ├── basemainnet │ ├── .chainId │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── ChainlinkOracle.json │ ├── ChainlinkOracle_Implementation.json │ ├── ChainlinkOracle_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── RedStoneOracle.json │ ├── RedStoneOracle_Implementation.json │ ├── RedStoneOracle_Proxy.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ ├── solcInputs │ │ ├── 04b8d48531fd1efbae754b96568494bd.json │ │ ├── 0f684409aa621941be6a37cef70844a1.json │ │ ├── 369540e457c3c93e79faa77ee00eacd5.json │ │ └── c3eebb33ec692fad160aed655c5e5531.json │ ├── wstETHOneJumpChainlinkOracle.json │ ├── wstETHOneJumpChainlinkOracle_Implementation.json │ ├── wstETHOneJumpChainlinkOracle_Proxy.json │ └── wsuperOETHb_ERC4626Oracle.json ├── basemainnet_addresses.json ├── basesepolia.json ├── basesepolia │ ├── .chainId │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── ChainlinkOracle.json │ ├── ChainlinkOracle_Implementation.json │ ├── ChainlinkOracle_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── RedStoneOracle.json │ ├── RedStoneOracle_Implementation.json │ ├── RedStoneOracle_Proxy.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ ├── solcInputs │ │ ├── 04b8d48531fd1efbae754b96568494bd.json │ │ ├── 0f684409aa621941be6a37cef70844a1.json │ │ └── c3eebb33ec692fad160aed655c5e5531.json │ ├── wstETHOneJumpChainlinkOracle.json │ ├── wstETHOneJumpChainlinkOracle_Implementation.json │ ├── wstETHOneJumpChainlinkOracle_Proxy.json │ └── wsuperOETHb_ERC4626Oracle.json ├── basesepolia_addresses.json ├── berachainbepolia.json ├── berachainbepolia │ ├── .chainId │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── ChainlinkOracle.json │ ├── ChainlinkOracle_Implementation.json │ ├── ChainlinkOracle_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── RedStoneOracle.json │ ├── RedStoneOracle_Implementation.json │ ├── RedStoneOracle_Proxy.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ └── solcInputs │ │ └── 9703a470efb9e8d7aa23c7bd832fbb1c.json ├── berachainbepolia_addresses.json ├── bscmainnet.json ├── bscmainnet │ ├── .chainId │ ├── AnkrBNBOracle.json │ ├── AnkrBNBOracle_Implementation.json │ ├── AnkrBNBOracle_Proxy.json │ ├── AsBNBOracle.json │ ├── AsBNBOracle_Implementation.json │ ├── AsBNBOracle_Proxy.json │ ├── BNBxOracle.json │ ├── BNBxOracle_Implementation.json │ ├── BNBxOracle_Proxy.json │ ├── BinanceOracle.json │ ├── BinanceOracle_Implementation.json │ ├── BinanceOracle_Proxy.json │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── ChainlinkOracle.json │ ├── ChainlinkOracle_Implementation.json │ ├── ChainlinkOracle_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── DevProxyAdmin.json │ ├── PendleOracle-PT-SolvBTC.BBN-27MAR2025.json │ ├── PendleOracle-PT-SolvBTC.BBN-27MAR2025_Implementation.json │ ├── PendleOracle-PT-SolvBTC.BBN-27MAR2025_Proxy.json │ ├── PendleOracle-PT-SolvBTC.BBN-27MAR2025_Reference_PtToAsset.json │ ├── PendleOracle-PT-SolvBTC.BBN-27MAR2025_Reference_PtToAsset_Implementation.json │ ├── PendleOracle-PT-SolvBTC.BBN-27MAR2025_Reference_PtToAsset_Proxy.json │ ├── PendleOracle-PT-clisBNB-24APR2025.json │ ├── PendleOracle-PT-clisBNB-24APR2025_Implementation.json │ ├── PendleOracle-PT-clisBNB-24APR2025_Proxy.json │ ├── PendleOracle-PT-clisBNB-24APR2025_Reference_PtToAsset.json │ ├── PendleOracle-PT-clisBNB-24APR2025_Reference_PtToAsset_Implementation.json │ ├── PendleOracle-PT-clisBNB-24APR2025_Reference_PtToAsset_Proxy.json │ ├── PendleOracle-PT-sUSDe-26JUN2025.json │ ├── PendleOracle-PT-sUSDe-26JUN2025_Implementation.json │ ├── PendleOracle-PT-sUSDe-26JUN2025_Proxy.json │ ├── PendleOracle-PT-sUSDe-26JUN2025_Reference_PtToAsset.json │ ├── PendleOracle-PT-sUSDe-26JUN2025_Reference_PtToAsset_Implementation.json │ ├── PendleOracle-PT-sUSDe-26JUN2025_Reference_PtToAsset_Proxy.json │ ├── PythOracle.json │ ├── PythOracle_Implementation.json │ ├── PythOracle_Proxy.json │ ├── RedStoneOracle.json │ ├── RedStoneOracle_Implementation.json │ ├── RedStoneOracle_Proxy.json │ ├── ReferenceOracle.json │ ├── ReferenceOracle_Implementation.json │ ├── ReferenceOracle_Proxy.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ ├── SlisBNBOracle.json │ ├── SlisBNBOracle_Implementation.json │ ├── SlisBNBOracle_Proxy.json │ ├── SolvBTC.BBN_OneJumpRedStoneOracle.json │ ├── SolvBTC.BBN_OneJumpRedStoneOracle_Implementation.json │ ├── SolvBTC.BBN_OneJumpRedStoneOracle_Proxy.json │ ├── StkBNBOracle.json │ ├── StkBNBOracle_Implementation.json │ ├── StkBNBOracle_Proxy.json │ ├── WBETHOracle.json │ ├── WBETHOracle_Implementation.json │ ├── WBETHOracle_Proxy.json │ ├── sUSDeOneJumpChainlinkOracle.json │ ├── sUSDeOneJumpChainlinkOracle_Implementation.json │ ├── sUSDeOneJumpChainlinkOracle_Proxy.json │ ├── sUSDeOneJumpRedstoneOracle.json │ ├── sUSDeOneJumpRedstoneOracle_Implementation.json │ ├── sUSDeOneJumpRedstoneOracle_Proxy.json │ ├── solcInputs │ │ ├── 0bebc4f35e59fb8446bd3ebaaccae910.json │ │ ├── 0e89febeebc7444140de8e67c9067d2c.json │ │ ├── 14552d52675fedf77ca6b2dd8b471565.json │ │ ├── 20abf9c935c457314764c04a2f2833b7.json │ │ ├── 2573dc270dc689bc0298b2a1866d6e88.json │ │ ├── 53b07f2899bbd8256f79840e3cbeb06b.json │ │ ├── 5eefab25ac812df21160bd253cc12328.json │ │ ├── 66e26ae62d34867b0322ef873d8c1777.json │ │ ├── 6aede02a1ea73715bd2f7f2e6dad96c7.json │ │ ├── 8e19d72e166e56d88f764fda7692397b.json │ │ ├── 99b3bea8181cef11bcfb39c4212459c2.json │ │ ├── aae9f1601b873a5a4704ede73ede10cb.json │ │ ├── b6239049fc8efa76629a29860a4d9026.json │ │ ├── cb3982d57490c86322c7d5373ee9afb2.json │ │ ├── d2941541ad0a5d456f9efff480594d3e.json │ │ ├── d647123072ba05451b756817f39951df.json │ │ └── e0e84cc585c5459e8a1a18f2ff8db0e0.json │ ├── weETHOneJumpChainlinkOracle.json │ ├── weETHOneJumpChainlinkOracle_Implementation.json │ ├── weETHOneJumpChainlinkOracle_Proxy.json │ ├── weETHOneJumpRedstoneOracle.json │ ├── weETHOneJumpRedstoneOracle_Implementation.json │ ├── weETHOneJumpRedstoneOracle_Proxy.json │ ├── wstETHOneJumpChainlinkOracle.json │ ├── wstETHOneJumpChainlinkOracle_Implementation.json │ ├── wstETHOneJumpChainlinkOracle_Proxy.json │ ├── wstETHOneJumpRedstoneOracle.json │ ├── wstETHOneJumpRedstoneOracle_Implementation.json │ ├── wstETHOneJumpRedstoneOracle_Proxy.json │ ├── xSolvBTCOneJumpRedStoneOracle.json │ ├── xSolvBTCOneJumpRedStoneOracle_Implementation.json │ └── xSolvBTCOneJumpRedStoneOracle_Proxy.json ├── bscmainnet_addresses.json ├── bsctestnet.json ├── bsctestnet │ ├── .chainId │ ├── AnkrBNBOracle.json │ ├── AnkrBNBOracle_Implementation.json │ ├── AnkrBNBOracle_Proxy.json │ ├── AsBNBOracle.json │ ├── AsBNBOracle_Implementation.json │ ├── AsBNBOracle_Proxy.json │ ├── BNBxOracle.json │ ├── BNBxOracle_Implementation.json │ ├── BNBxOracle_Proxy.json │ ├── BinanceOracle.json │ ├── BinanceOracle_Implementation.json │ ├── BinanceOracle_Proxy.json │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── ChainlinkOracle.json │ ├── ChainlinkOracle_Implementation.json │ ├── ChainlinkOracle_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── MockAnkrBNB.json │ ├── MockAsBNB.json │ ├── MockAsBNBMinter.json │ ├── MockPendlePtOracle.json │ ├── MockWBETH.json │ ├── PendleOracle-PT-SolvBTC.BBN-27MAR2025.json │ ├── PendleOracle-PT-SolvBTC.BBN-27MAR2025_Implementation.json │ ├── PendleOracle-PT-SolvBTC.BBN-27MAR2025_Proxy.json │ ├── PendleOracle-PT-clisBNB-24APR2025.json │ ├── PendleOracle-PT-clisBNB-24APR2025_Implementation.json │ ├── PendleOracle-PT-clisBNB-24APR2025_Proxy.json │ ├── PendleOracle-PT-sUSDe-26JUN2025.json │ ├── PendleOracle-PT-sUSDe-26JUN2025_Implementation.json │ ├── PendleOracle-PT-sUSDe-26JUN2025_Proxy.json │ ├── PythOracle.json │ ├── PythOracle_Implementation.json │ ├── PythOracle_Proxy.json │ ├── RedStoneOracle.json │ ├── RedStoneOracle_Implementation.json │ ├── RedStoneOracle_Proxy.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ ├── SlisBNBOracle.json │ ├── SlisBNBOracle_Implementation.json │ ├── SlisBNBOracle_Proxy.json │ ├── SolvBTC.BBN_OneJumpRedStoneOracle.json │ ├── SolvBTC.BBN_OneJumpRedStoneOracle_Implementation.json │ ├── SolvBTC.BBN_OneJumpRedStoneOracle_Proxy.json │ ├── StkBNBOracle.json │ ├── StkBNBOracle_Implementation.json │ ├── StkBNBOracle_Proxy.json │ ├── WBETHOracle.json │ ├── WBETHOracle_Implementation.json │ ├── WBETHOracle_Proxy.json │ ├── sUSDeOneJumpChainlinkOracle.json │ ├── sUSDeOneJumpChainlinkOracle_Implementation.json │ ├── sUSDeOneJumpChainlinkOracle_Proxy.json │ ├── sUSDeOneJumpRedstoneOracle.json │ ├── sUSDeOneJumpRedstoneOracle_Implementation.json │ ├── sUSDeOneJumpRedstoneOracle_Proxy.json │ ├── solcInputs │ │ ├── 0bebc4f35e59fb8446bd3ebaaccae910.json │ │ ├── 0e89febeebc7444140de8e67c9067d2c.json │ │ ├── 131f58942628e21632de19506977a910.json │ │ ├── 144b49e8aec3add79553ba273ea32d00.json │ │ ├── 14552d52675fedf77ca6b2dd8b471565.json │ │ ├── 20abf9c935c457314764c04a2f2833b7.json │ │ ├── 49c484f7dee06f7d516c3b0bdb3fb2af.json │ │ ├── 503f2e4e766f3be923fadf8030a5470f.json │ │ ├── 53b07f2899bbd8256f79840e3cbeb06b.json │ │ ├── 5eefab25ac812df21160bd253cc12328.json │ │ ├── 66e26ae62d34867b0322ef873d8c1777.json │ │ ├── 6aede02a1ea73715bd2f7f2e6dad96c7.json │ │ ├── 6cbd6773cfb72588e3c8c8a99fa8d8b1.json │ │ ├── 736d67ad7b38d1f4e4d44287a62f9e13.json │ │ ├── 814e0fa78252010542d2571cb1efedf7.json │ │ ├── 86afb48e080961463ac5bcb641c3603b.json │ │ ├── 99b3bea8181cef11bcfb39c4212459c2.json │ │ ├── b39d33092f7dd383ae3a042566194132.json │ │ ├── cb3982d57490c86322c7d5373ee9afb2.json │ │ ├── ce698515509ffbce3141a127fecea5ea.json │ │ ├── d2941541ad0a5d456f9efff480594d3e.json │ │ ├── d647123072ba05451b756817f39951df.json │ │ └── e0e84cc585c5459e8a1a18f2ff8db0e0.json │ ├── weETHOneJumpChainlinkOracle.json │ ├── weETHOneJumpChainlinkOracle_Implementation.json │ ├── weETHOneJumpChainlinkOracle_Proxy.json │ ├── weETHOneJumpRedstoneOracle.json │ ├── weETHOneJumpRedstoneOracle_Implementation.json │ ├── weETHOneJumpRedstoneOracle_Proxy.json │ ├── wstETHOneJumpChainlinkOracle.json │ ├── wstETHOneJumpChainlinkOracle_Implementation.json │ ├── wstETHOneJumpChainlinkOracle_Proxy.json │ ├── wstETHOneJumpRedstoneOracle.json │ ├── wstETHOneJumpRedstoneOracle_Implementation.json │ ├── wstETHOneJumpRedstoneOracle_Proxy.json │ ├── xSolvBTCOneJumpRedStoneOracle.json │ ├── xSolvBTCOneJumpRedStoneOracle_Implementation.json │ └── xSolvBTCOneJumpRedStoneOracle_Proxy.json ├── bsctestnet_addresses.json ├── ethereum.json ├── ethereum │ ├── .chainId │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── ChainlinkOracle.json │ ├── ChainlinkOracle_Implementation.json │ ├── ChainlinkOracle_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── DevProxyAdmin.json │ ├── LBTCOneJumpRedStoneOracle.json │ ├── LBTCOneJumpRedStoneOracle_Implementation.json │ ├── LBTCOneJumpRedStoneOracle_Proxy.json │ ├── PendleOracle-PT-weETH-26DEC2024.json │ ├── PendleOracle-PT-weETH-26DEC2024_Implementation.json │ ├── PendleOracle-PT-weETH-26DEC2024_Proxy.json │ ├── PendleOracle-PT-weETH-26DEC2024_Reference.json │ ├── PendleOracle-PT-weETH-26DEC2024_Reference_Implementation.json │ ├── PendleOracle-PT-weETH-26DEC2024_Reference_Proxy.json │ ├── PendleOracle_PT_USDe_27MAR2025.json │ ├── PendleOracle_PT_USDe_27MAR2025_Implementation.json │ ├── PendleOracle_PT_USDe_27MAR2025_Proxy.json │ ├── PendleOracle_PT_USDe_27MAR2025_Reference.json │ ├── PendleOracle_PT_USDe_27MAR2025_Reference_Implementation.json │ ├── PendleOracle_PT_USDe_27MAR2025_Reference_Proxy.json │ ├── PendleOracle_PT_sUSDe_27MAR2025.json │ ├── PendleOracle_PT_sUSDe_27MAR2025_Implementation.json │ ├── PendleOracle_PT_sUSDe_27MAR2025_Proxy.json │ ├── PendleOracle_PT_sUSDe_27MAR2025_Reference.json │ ├── PendleOracle_PT_sUSDe_27MAR2025_Reference_Implementation.json │ ├── PendleOracle_PT_sUSDe_27MAR2025_Reference_Proxy.json │ ├── RedStoneOracle.json │ ├── RedStoneOracle_Implementation.json │ ├── RedStoneOracle_Proxy.json │ ├── ReferenceOracle.json │ ├── ReferenceOracle_Implementation.json │ ├── ReferenceOracle_Proxy.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ ├── SFraxOracle.json │ ├── SFraxOracle_Implementation.json │ ├── SFraxOracle_Proxy.json │ ├── SFrxETHOracle.json │ ├── SFrxETHOracle_Implementation.json │ ├── SFrxETHOracle_Proxy.json │ ├── WeETHAccountantOracle_weETHs.json │ ├── WeETHAccountantOracle_weETHs_Implementation.json │ ├── WeETHAccountantOracle_weETHs_Proxy.json │ ├── WeETHOracle_Equivalence.json │ ├── WeETHOracle_Equivalence_Implementation.json │ ├── WeETHOracle_Equivalence_Proxy.json │ ├── WeETHOracle_NonEquivalence.json │ ├── WeETHOracle_NonEquivalence_Implementation.json │ ├── WeETHOracle_NonEquivalence_Proxy.json │ ├── WstETHOracle_Equivalence.json │ ├── WstETHOracle_Equivalence_Implementation.json │ ├── WstETHOracle_Equivalence_Proxy.json │ ├── WstETHOracle_NonEquivalence.json │ ├── WstETHOracle_NonEquivalence_Implementation.json │ ├── WstETHOracle_NonEquivalence_Proxy.json │ ├── eBTCAccountantOracle.json │ ├── eBTCAccountantOracle_Implementation.json │ ├── eBTCAccountantOracle_Proxy.json │ ├── ezETHOneJumpChainlinkOracle.json │ ├── ezETHOneJumpChainlinkOracle_Implementation.json │ ├── ezETHOneJumpChainlinkOracle_Proxy.json │ ├── ezETHOneJumpRedStoneOracle.json │ ├── ezETHOneJumpRedStoneOracle_Implementation.json │ ├── ezETHOneJumpRedStoneOracle_Proxy.json │ ├── pufETHOneJumpRedStoneOracle.json │ ├── pufETHOneJumpRedStoneOracle_Implementation.json │ ├── pufETHOneJumpRedStoneOracle_Proxy.json │ ├── rsETHOneJumpChainlinkOracle.json │ ├── rsETHOneJumpChainlinkOracle_Implementation.json │ ├── rsETHOneJumpChainlinkOracle_Proxy.json │ ├── rsETHOneJumpRedStoneOracle.json │ ├── rsETHOneJumpRedStoneOracle_Implementation.json │ ├── rsETHOneJumpRedStoneOracle_Proxy.json │ ├── sUSDS_ERC4626Oracle.json │ ├── sUSDe_ERC4626Oracle.json │ ├── solcInputs │ │ ├── 04b8d48531fd1efbae754b96568494bd.json │ │ ├── 04e4e9272baf051bc64349e36ce2636f.json │ │ ├── 09983d8c7b2b8810c675e65f6220c268.json │ │ ├── 0e89febeebc7444140de8e67c9067d2c.json │ │ ├── 20abf9c935c457314764c04a2f2833b7.json │ │ ├── 2675f6933965af498101c80cb5610aca.json │ │ ├── 61a63fbc062c2591c6768138f59373e1.json │ │ ├── 643c04e89f008dea200654c141acbf47.json │ │ ├── 7b8551538396b38af0fe946740b984fc.json │ │ ├── 8e19d72e166e56d88f764fda7692397b.json │ │ ├── 94bfc5063ff1e6d8e2de1792750dac25.json │ │ ├── 99b3bea8181cef11bcfb39c4212459c2.json │ │ ├── c3627496deae3f549b7b46b372e638a8.json │ │ ├── c3eebb33ec692fad160aed655c5e5531.json │ │ ├── c5ec17691df5041aeaa94cb65949c153.json │ │ ├── c6174c83da2c4c9e01c4543fbd822859.json │ │ ├── c9234768a0e90787a3e044ab631ca909.json │ │ ├── d185d116dd1c48d32d2e3ff045d30d4c.json │ │ └── e2bc12b3d18327797d739ca7bdb8b6fc.json │ ├── yvUSDC-1_ERC4626Oracle.json │ ├── yvUSDS-1_ERC4626Oracle.json │ ├── yvUSDT-1_ERC4626Oracle.json │ └── yvWETH-1_ERC4626Oracle.json ├── ethereum_addresses.json ├── opbnbmainnet.json ├── opbnbmainnet │ ├── .chainId │ ├── BinanceOracle.json │ ├── BinanceOracle_Implementation.json │ ├── BinanceOracle_Proxy.json │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ └── solcInputs │ │ ├── 0e89febeebc7444140de8e67c9067d2c.json │ │ └── 1e37f6e5d619feb70cefe47611ec524e.json ├── opbnbmainnet_addresses.json ├── opbnbtestnet.json ├── opbnbtestnet │ ├── .chainId │ ├── BinanceOracle.json │ ├── BinanceOracle_Implementation.json │ ├── BinanceOracle_Proxy.json │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ └── solcInputs │ │ ├── 0e89febeebc7444140de8e67c9067d2c.json │ │ └── 3c996a10e894dc6fe519573ed39fc60f.json ├── opbnbtestnet_addresses.json ├── opmainnet.json ├── opmainnet │ ├── .chainId │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── RedStoneOracle.json │ ├── RedStoneOracle_Implementation.json │ ├── RedStoneOracle_Proxy.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ ├── SequencerChainlinkOracle.json │ ├── SequencerChainlinkOracle_Implementation.json │ ├── SequencerChainlinkOracle_Proxy.json │ └── solcInputs │ │ └── c9234768a0e90787a3e044ab631ca909.json ├── opmainnet_addresses.json ├── opsepolia.json ├── opsepolia │ ├── .chainId │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── ChainlinkOracle.json │ ├── ChainlinkOracle_Implementation.json │ ├── ChainlinkOracle_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ └── solcInputs │ │ ├── 0e89febeebc7444140de8e67c9067d2c.json │ │ └── d185d116dd1c48d32d2e3ff045d30d4c.json ├── opsepolia_addresses.json ├── sepolia.json ├── sepolia │ ├── .chainId │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── ChainlinkOracle.json │ ├── ChainlinkOracle_Implementation.json │ ├── ChainlinkOracle_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── LBTCOneJumpRedStoneOracle.json │ ├── LBTCOneJumpRedStoneOracle_Implementation.json │ ├── LBTCOneJumpRedStoneOracle_Proxy.json │ ├── MockAccountant_eBTC.json │ ├── MockAccountant_weETHs.json │ ├── MockEtherFiLiquidityPool.json │ ├── MockPendleOracle_PT_USDe_27MAR2025.json │ ├── MockPendleOracle_PT_sUSDe_27MAR2025.json │ ├── MockPendlePtOracle.json │ ├── MockSFrax.json │ ├── MockSfrxEthFraxOracle.json │ ├── PendleOracle-PT-weETH-26DEC2024.json │ ├── PendleOracle-PT-weETH-26DEC2024_Implementation.json │ ├── PendleOracle-PT-weETH-26DEC2024_Proxy.json │ ├── PendleOracle_PT_USDe_27MAR2025.json │ ├── PendleOracle_PT_USDe_27MAR2025_Implementation.json │ ├── PendleOracle_PT_USDe_27MAR2025_Proxy.json │ ├── PendleOracle_PT_sUSDe_27MAR2025.json │ ├── PendleOracle_PT_sUSDe_27MAR2025_Implementation.json │ ├── PendleOracle_PT_sUSDe_27MAR2025_Proxy.json │ ├── RedStoneOracle.json │ ├── RedStoneOracle_Implementation.json │ ├── RedStoneOracle_Proxy.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ ├── SFraxOracle.json │ ├── SFraxOracle_Implementation.json │ ├── SFraxOracle_Proxy.json │ ├── SFrxETHOracle.json │ ├── SFrxETHOracle_Implementation.json │ ├── SFrxETHOracle_Proxy.json │ ├── WeETHAccountantOracle_weETHs.json │ ├── WeETHAccountantOracle_weETHs_Implementation.json │ ├── WeETHAccountantOracle_weETHs_Proxy.json │ ├── WeETHOracle.json │ ├── WeETHOracle_Implementation.json │ ├── WeETHOracle_Proxy.json │ ├── WstETHOracle.json │ ├── WstETHOracle_Implementation.json │ ├── WstETHOracle_Proxy.json │ ├── eBTCAccountantOracle.json │ ├── eBTCAccountantOracle_Implementation.json │ ├── eBTCAccountantOracle_Proxy.json │ ├── ezETHOneJumpChainlinkOracle.json │ ├── ezETHOneJumpChainlinkOracle_Implementation.json │ ├── ezETHOneJumpChainlinkOracle_Proxy.json │ ├── ezETHOneJumpRedStoneOracle.json │ ├── ezETHOneJumpRedStoneOracle_Implementation.json │ ├── ezETHOneJumpRedStoneOracle_Proxy.json │ ├── pufETHOneJumpRedStoneOracle.json │ ├── pufETHOneJumpRedStoneOracle_Implementation.json │ ├── pufETHOneJumpRedStoneOracle_Proxy.json │ ├── rsETHOneJumpChainlinkOracle.json │ ├── rsETHOneJumpChainlinkOracle_Implementation.json │ ├── rsETHOneJumpChainlinkOracle_Proxy.json │ ├── rsETHOneJumpRedStoneOracle.json │ ├── rsETHOneJumpRedStoneOracle_Implementation.json │ ├── rsETHOneJumpRedStoneOracle_Proxy.json │ ├── sUSDS_ERC4626Oracle.json │ ├── sUSDe_ERC4626Oracle.json │ ├── solcInputs │ │ ├── 04b8d48531fd1efbae754b96568494bd.json │ │ ├── 04e4e9272baf051bc64349e36ce2636f.json │ │ ├── 09983d8c7b2b8810c675e65f6220c268.json │ │ ├── 0e89febeebc7444140de8e67c9067d2c.json │ │ ├── 10211ffe5f5d2e235e8b1b524375aa59.json │ │ ├── 20abf9c935c457314764c04a2f2833b7.json │ │ ├── 22740d447fc1d2a214063808c7fd3297.json │ │ ├── 362cf09683647ff886ba5212c34c9c04.json │ │ ├── 44d276ef597ed410d246aeb39628d203.json │ │ ├── 61a63fbc062c2591c6768138f59373e1.json │ │ ├── 94bfc5063ff1e6d8e2de1792750dac25.json │ │ ├── 9c723b598c150ce8056583ac97334383.json │ │ ├── c3eebb33ec692fad160aed655c5e5531.json │ │ ├── c5ec17691df5041aeaa94cb65949c153.json │ │ ├── c9234768a0e90787a3e044ab631ca909.json │ │ ├── cd34c80c0222fcfecdfcd96bccbdb60b.json │ │ ├── d185d116dd1c48d32d2e3ff045d30d4c.json │ │ ├── d7071d7f42106bbbe692dda5807a1305.json │ │ ├── e2bc12b3d18327797d739ca7bdb8b6fc.json │ │ └── f5d4d6aee7a4e630f36ae4eef8377cf3.json │ ├── yvUSDC-1_ERC4626Oracle.json │ ├── yvUSDS-1_ERC4626Oracle.json │ ├── yvUSDT-1_ERC4626Oracle.json │ └── yvWETH-1_ERC4626Oracle.json ├── sepolia_addresses.json ├── unichainmainnet.json ├── unichainmainnet │ ├── .chainId │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── RedStoneOracle.json │ ├── RedStoneOracle_Implementation.json │ ├── RedStoneOracle_Proxy.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ └── solcInputs │ │ └── c3eebb33ec692fad160aed655c5e5531.json ├── unichainmainnet_addresses.json ├── unichainsepolia.json ├── unichainsepolia │ ├── .chainId │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── RedStoneOracle.json │ ├── RedStoneOracle_Implementation.json │ ├── RedStoneOracle_Proxy.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ └── solcInputs │ │ ├── c9234768a0e90787a3e044ab631ca909.json │ │ └── ed3de5d7af38f205c4c23fbb23f18a00.json ├── unichainsepolia_addresses.json ├── zksyncmainnet.json ├── zksyncmainnet │ ├── .chainId │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── ChainlinkOracle.json │ ├── ChainlinkOracle_Implementation.json │ ├── ChainlinkOracle_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── RedStoneOracle.json │ ├── RedStoneOracle_Implementation.json │ ├── RedStoneOracle_Proxy.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ ├── ZkETHOracle.json │ ├── ZkETHOracle_Implementation.json │ ├── ZkETHOracle_Proxy.json │ ├── solcInputs │ │ ├── 222482d78b5fc1b4543fc440938169cf.json │ │ ├── 9895aa2d892e785997f36f455a3dcc39.json │ │ ├── d14112d82bb23a35dc687350b4e61e84.json │ │ └── e092fdbd86abd3281b70dd1ac599d6ef.json │ ├── wUSDM_ERC4626Oracle.json │ ├── wstETHOneJumpChainlinkOracle.json │ ├── wstETHOneJumpChainlinkOracle_Implementation.json │ └── wstETHOneJumpChainlinkOracle_Proxy.json ├── zksyncmainnet_addresses.json ├── zksyncsepolia.json ├── zksyncsepolia │ ├── .chainId │ ├── BoundValidator.json │ ├── BoundValidator_Implementation.json │ ├── BoundValidator_Proxy.json │ ├── ChainlinkOracle.json │ ├── ChainlinkOracle_Implementation.json │ ├── ChainlinkOracle_Proxy.json │ ├── DefaultProxyAdmin.json │ ├── RedStoneOracle.json │ ├── RedStoneOracle_Implementation.json │ ├── RedStoneOracle_Proxy.json │ ├── ResilientOracle.json │ ├── ResilientOracle_Implementation.json │ ├── ResilientOracle_Proxy.json │ ├── ZkETHOracle.json │ ├── ZkETHOracle_Implementation.json │ ├── ZkETHOracle_Proxy.json │ ├── solcInputs │ │ ├── 222482d78b5fc1b4543fc440938169cf.json │ │ ├── 7b38f0bb1e39a4d8519998be3af17083.json │ │ ├── 9895aa2d892e785997f36f455a3dcc39.json │ │ ├── cc1afdf11a23563c8dca92a85f47d6b1.json │ │ └── e092fdbd86abd3281b70dd1ac599d6ef.json │ ├── wUSDM_ERC4626Oracle.json │ ├── wstETHOneJumpChainlinkOracle.json │ ├── wstETHOneJumpChainlinkOracle_Implementation.json │ └── wstETHOneJumpChainlinkOracle_Proxy.json └── zksyncsepolia_addresses.json ├── docgen-templates ├── common.hbs ├── helpers.ts ├── page.hbs └── properties.ts ├── docs └── CONTRIBUTING.md ├── funding.json ├── hardhat.config.ts ├── hardhat.config.zksync.ts ├── helpers ├── deploymentConfig.ts └── deploymentUtils.ts ├── marketing-assets └── oracles.png ├── networks └── mainnet.json ├── package.json ├── patches └── @defi-wonderland+smock+2.4.0.patch ├── test ├── AnkrBNBOracle.ts ├── BNBxOracle.ts ├── BinanceOracle.ts ├── BoundValidator.ts ├── ChainlinkOracle.ts ├── ERC4626Oracle.ts ├── OneJumpOracle.ts ├── PendleOracle.ts ├── PivotPythOracle.ts ├── ReferenceOracle.ts ├── ResilientOracle.ts ├── SFraxOracle.ts ├── SFrxETHOracle.ts ├── SequencerChainlinkOracle.ts ├── SlisBNBOracle.ts ├── StkBNBOracle.ts ├── WBETHOracle.ts ├── WeETHOracle.ts ├── WstETHOracleV2.ts ├── ZkETHOracle.ts ├── asBNBOracle.ts ├── fork │ ├── abi │ │ └── wstETH.json │ ├── bnb-price.ts │ ├── btc-price.ts │ ├── core-compatibility.ts │ ├── utils.ts │ ├── validate-price-config.ts │ └── wstETHOracle.ts ├── types.ts └── utils │ ├── data.ts │ ├── makeChainlinkOracle.ts │ ├── makePair.ts │ ├── makeToken.ts │ ├── makeVToken.ts │ └── time.ts ├── tsconfig.json └── yarn.lock /.czrc: -------------------------------------------------------------------------------- 1 | { 2 | "path": "cz-conventional-changelog" 3 | } 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # All files 7 | [*] 8 | charset = utf-8 9 | end_of_line = lf 10 | indent_size = 2 11 | indent_style = space 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | 15 | [*.sol] 16 | indent_size = 4 17 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # true or false 2 | FORK=false 3 | FORKED_NETWORK=bscmainnet 4 | 5 | DEPLOYER_PRIVATE_KEY= 6 | 7 | ## Archive nodes 8 | ARCHIVE_NODE_bsctestnet=https://bsc-testnet.nodereal.io/v1/ 9 | ARCHIVE_NODE_bscmainnet=https://bsc-mainnet.nodereal.io/v1/ 10 | #ARCHIVE_NODE_bscmainnet=http://127.0.0.1:1248 11 | ARCHIVE_NODE_sepolia=https://ethereum-sepolia.blockpi.network/v1/rpc/public 12 | ARCHIVE_NODE_ethereum=https://eth-mainnet.nodereal.io/v1/ 13 | #ARCHIVE_NODE_ethereum=http://127.0.0.1:1248 14 | #ARCHIVE_NODE_opbnbtestnet=https://opbnb-testnet.nodereal.io/v1/ 15 | #ARCHIVE_NODE_opbnbmainnet=https://opbnb-mainnet.nodereal.io/v1/ 16 | #ARCHIVE_NODE_arbitrumsepolia=https://sepolia-rollup.arbitrum.io/rpc 17 | #ARCHIVE_NODE_arbitrumone=https://open-platform.nodereal.io//arbitrum-nitro/ 18 | #ARCHIVE_NODE_zksyncsepolia=https://zksync-sepolia.g.alchemy.com/v2/ 19 | #ARCHIVE_NODE_zksyncmainnet=https://open-platform.nodereal.io//zksync 20 | #ARCHIVE_NODE_opsepolia=https://sepolia.optimism.io 21 | #ARCHIVE_NODE_opmainnet=https://opt-mainnet.nodereal.io/v1/ 22 | #ARCHIVE_NODE_basesepolia=https://sepolia.base.org 23 | #ARCHIVE_NODE_basemainnet=https://open-platform.nodereal.io//base 24 | #ARCHIVE_NODE_unichainsepolia=https://unichain-sepolia.g.alchemy.com/v2/ 25 | #ARCHIVE_NODE_unichainmainnet=https://unichain-mainnet.g.alchemy.com/v2/ 26 | #ARCHIVE_NODE_berachainbepolia=https://berachain-bepolia.g.alchemy.com/v2/ 27 | 28 | ETHERSCAN_API_KEY= 29 | REPORT_GAS= -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # directories 2 | .yarn/ 3 | **/.coverage_artifacts 4 | **/.coverage_cache 5 | **/.coverage_contracts 6 | **/artifacts 7 | **/arifacts-zk 8 | **/build 9 | **/cache 10 | **/cache-zk 11 | **/coverage 12 | **/dist 13 | **/node_modules 14 | **/types 15 | 16 | # files 17 | *.env 18 | *.log 19 | .pnp.* 20 | coverage.json 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "airbnb-base", 4 | "plugin:@typescript-eslint/eslint-recommended", 5 | "plugin:@typescript-eslint/recommended", 6 | "plugin:import/recommended", 7 | "prettier" 8 | ], 9 | "parser": "@typescript-eslint/parser", 10 | "parserOptions": { 11 | "project": ".eslinttsconfigrc" 12 | }, 13 | "plugins": ["@typescript-eslint"], 14 | "root": true, 15 | "rules": { 16 | "import/extensions": 0, 17 | "import/prefer-default-export": 0, 18 | "camelcase": 1, 19 | "no-await-in-loop": 1, 20 | "no-restricted-syntax": 1, 21 | "no-shadow": 0, 22 | "@typescript-eslint/no-shadow": 2, 23 | "import/no-extraneous-dependencies": [ 24 | "error", 25 | { 26 | "devDependencies": ["test/**", "hardhat.config.ts", "hardhat.config.zksync.ts"] 27 | } 28 | ], 29 | "@typescript-eslint/no-floating-promises": [ 30 | "error", 31 | { 32 | "ignoreIIFE": true, 33 | "ignoreVoid": true 34 | } 35 | ], 36 | "@typescript-eslint/no-inferrable-types": "off", 37 | "@typescript-eslint/no-unused-vars": [ 38 | "error", 39 | { 40 | "argsIgnorePattern": "_", 41 | "varsIgnorePattern": "_" 42 | } 43 | ], 44 | "prefer-destructuring": [ 45 | "error", 46 | { 47 | "array": false, 48 | "object": true 49 | }, 50 | { 51 | "enforceForRenamedProperties": false 52 | } 53 | ] 54 | }, 55 | "settings": { 56 | "import/resolver": { 57 | "node": { 58 | "extensions": [".js", ".jsx", ".ts", ".tsx"] 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /.eslinttsconfigrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": [ 4 | "typechain-types", 5 | "deploy", 6 | "test", 7 | "tasks", 8 | "docgen-templates", 9 | "commitlint.config.js", 10 | "./hardhat.config.zksync.ts" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | 4 | 5 | Resolves # 6 | 7 | ## Checklist 8 | 9 | 13 | 14 | - [ ] I have updated the documentation to account for the changes in the code. 15 | - [ ] If I added new functionality, I added tests covering it. 16 | - [ ] If I fixed a bug, I added a test preventing this bug from silently reappearing again. 17 | - [ ] My contribution follows [Venus contribution guidelines](docs/CONTRIBUTING.md). 18 | -------------------------------------------------------------------------------- /.github/workflows/cd.yaml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - develop 8 | 9 | jobs: 10 | release: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v3 15 | with: 16 | fetch-depth: 0 17 | persist-credentials: false 18 | 19 | - uses: actions/setup-node@v3 20 | with: 21 | cache: "yarn" 22 | 23 | - name: Install dependencies 24 | # Hack to get around failing "ethereumjs-abi The remote archive doesn't match the expected checksum" error 25 | run: YARN_CHECKSUM_BEHAVIOR=update yarn 26 | 27 | - name: Build 28 | run: yarn build 29 | 30 | - name: Release 31 | env: 32 | GITHUB_TOKEN: ${{ secrets.VENUS_TOOLS_TOKEN }} 33 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 34 | GIT_AUTHOR_NAME: Venus Tools 35 | GIT_AUTHOR_EMAIL: tools@venus.io 36 | GIT_COMMITTER_NAME: Venus Tools 37 | GIT_COMMITTER_EMAIL: tools@venus.io 38 | run: yarn semantic-release 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # directories 2 | .yarn/* 3 | !.yarn/patches 4 | !.yarn/releases 5 | !.yarn/plugins 6 | !.yarn/sdks 7 | !.yarn/versions 8 | **/artifacts 9 | **/artifacts-zk 10 | **/build 11 | **/cache 12 | **/cache-zk 13 | **/coverage 14 | **/.coverage_artifacts 15 | **/.coverage_cache 16 | **/.coverage_contracts 17 | **/dist 18 | **/node_modules 19 | .openzeppelin 20 | typechain-types 21 | 22 | # files 23 | *.env 24 | *.log 25 | .pnp.* 26 | coverage.json 27 | npm-debug.log* 28 | yarn-debug.log* 29 | yarn-error.log* 30 | 31 | # local 32 | deployments/localhost 33 | 34 | # docs 35 | docs 36 | 37 | 38 | deployments/hardhat 39 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no -- commitlint --edit ${1} --config ./commitlint.config.js 5 | -------------------------------------------------------------------------------- /.lintstagedrc: -------------------------------------------------------------------------------- 1 | { 2 | "*.{js,json,md,sol,ts,yaml,yml}": [ 3 | "prettier --config ./.prettierrc.yaml --write" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .github 2 | .yarn 3 | contracts 4 | deploy 5 | deployments 6 | docs 7 | networks 8 | test 9 | .npmignore 10 | hardhat.config.ts 11 | hardhat.config.zksync.ts 12 | .yarnrc.yml 13 | .solhintignore 14 | .solhint.json 15 | .solcover.js 16 | .prettierrc.yaml 17 | .prettierignore 18 | .npmrc 19 | .lintstagedrc 20 | .gitignore 21 | .eslintrc.yaml 22 | .eslintignore 23 | .editorconfig 24 | .czrc 25 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # directories 2 | .yarn/ 3 | **/.coverage_artifacts 4 | **/.coverage_cache 5 | **/.coverage_contracts 6 | **/artifacts 7 | **/artifacts-zk 8 | **/build 9 | **/cache 10 | **/cache-zk 11 | **/coverage 12 | **/dist 13 | **/node_modules 14 | **/typechain-types 15 | 16 | # files 17 | *.env 18 | *.log 19 | .pnp.* 20 | coverage.json 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | CHANGELOG.md 25 | -------------------------------------------------------------------------------- /.prettierrc.yaml: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": avoid, 3 | "bracketSpacing": true, 4 | "endOfLine": "lf", 5 | "importOrder": ["module-alias/register", "", "^[./]"], 6 | "importOrderParserPlugins": ["typescript"], 7 | "importOrderSeparation": true, 8 | "importOrderSortSpecifiers": true, 9 | "printWidth": 120, 10 | "singleQuote": false, 11 | "tabWidth": 2, 12 | "trailingComma": all, 13 | "overrides": [{ "files": "*.sol", "options": { "tabWidth": 4 } }], 14 | } 15 | -------------------------------------------------------------------------------- /.releaserc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | [ 4 | "@semantic-release/commit-analyzer", 5 | { 6 | "preset": "conventionalcommits", 7 | "releaseRules": [ 8 | {"breaking": true, "release": "major"}, 9 | { 10 | "type": "build", 11 | "release": false 12 | }, 13 | { 14 | "type": "chore", 15 | "release": false 16 | }, 17 | { 18 | "type": "docs", 19 | "release": "patch" 20 | }, 21 | { 22 | "type": "ci", 23 | "release": false 24 | }, 25 | { 26 | "type": "feat", 27 | "release": "minor" 28 | }, 29 | { 30 | "type": "fix", 31 | "release": "patch" 32 | }, 33 | { 34 | "type": "refactor", 35 | "release": "patch" 36 | }, 37 | { 38 | "type": "test", 39 | "release": false 40 | } 41 | ], 42 | "parserOpts": { 43 | "noteKeywords": [ 44 | "BREAKING CHANGE", 45 | "BREAKING CHANGES" 46 | ] 47 | } 48 | } 49 | ], 50 | [ 51 | "@semantic-release/release-notes-generator", 52 | { 53 | "preset": "conventionalcommits" 54 | } 55 | ], 56 | [ 57 | "@semantic-release/changelog", 58 | { 59 | "changelogFile": "CHANGELOG.md" 60 | } 61 | ], 62 | [ 63 | "@semantic-release/npm", 64 | { 65 | "npmPublish": true 66 | } 67 | ], 68 | [ 69 | "@semantic-release/git", 70 | { 71 | "assets": [ 72 | "package.json", 73 | "CHANGELOG.md" 74 | ], 75 | "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" 76 | } 77 | ] 78 | ], 79 | "branches": [ 80 | { 81 | "name": "main" 82 | }, 83 | { 84 | "name": "develop", 85 | "prerelease": "dev" 86 | } 87 | ] 88 | } 89 | -------------------------------------------------------------------------------- /.solcover.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | port: 8555, 3 | providerOpts: { 4 | // See example coverage settings at https://github.com/sc-forks/solidity-coverage 5 | gas: 0xfffffff, 6 | gasPrice: 0x01, 7 | }, 8 | mocha: { 9 | enableTimeouts: false, 10 | grep: /@gas|@no-cov/, 11 | invert: true, 12 | }, 13 | skipFiles: ["test", "oracles/mocks"], 14 | istanbulReporter: ["html", "lcov", "text", "json", "cobertura"], 15 | }; 16 | -------------------------------------------------------------------------------- /.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solhint:recommended", 3 | "plugins": ["prettier"], 4 | "rules": { 5 | "code-complexity": ["error", 8], 6 | "compiler-version": ["error", ">=0.5.0"], 7 | "const-name-snakecase": "warn", 8 | "constructor-syntax": "error", 9 | "func-visibility": ["error", { "ignoreConstructors": true }], 10 | "max-line-length": ["error", 120], 11 | "not-rely-on-time": "warn", 12 | "reason-string": ["warn", { "maxLength": 64 }], 13 | "ordering": "error" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.solhintignore: -------------------------------------------------------------------------------- 1 | # directories 2 | **/artifacts 3 | **/node_modules 4 | 5 | # Ignoring Pyth Interface because it was copied and linting would make the diff more complicated when updating 6 | contracts/interfaces/PythInterface.sol 7 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | plugins: 4 | - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs 5 | spec: "@yarnpkg/plugin-interactive-tools" 6 | 7 | yarnPath: .yarn/releases/yarn-3.2.0.cjs 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022 Venus Protocol. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /audits/013_oracles_peckshield_20230424.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/013_oracles_peckshield_20230424.pdf -------------------------------------------------------------------------------- /audits/016_oracles_hacken_20230426.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/016_oracles_hacken_20230426.pdf -------------------------------------------------------------------------------- /audits/024_oracles_certik_20230522.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/024_oracles_certik_20230522.pdf -------------------------------------------------------------------------------- /audits/026_oracles_openzeppelin_20230606.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/026_oracles_openzeppelin_20230606.pdf -------------------------------------------------------------------------------- /audits/043_getPrice_certik_20230717.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/043_getPrice_certik_20230717.pdf -------------------------------------------------------------------------------- /audits/045_getPrice_peckshield_20230712.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/045_getPrice_peckshield_20230712.pdf -------------------------------------------------------------------------------- /audits/090_wstETHOracle_certik_20240126.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/090_wstETHOracle_certik_20240126.pdf -------------------------------------------------------------------------------- /audits/093_wstETHOracle_quantstamp_20240220.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/093_wstETHOracle_quantstamp_20240220.pdf -------------------------------------------------------------------------------- /audits/097_twap_hashex_20240201.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/097_twap_hashex_20240201.pdf -------------------------------------------------------------------------------- /audits/098_correlated_token_oracles_certik_20240412.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/098_correlated_token_oracles_certik_20240412.pdf -------------------------------------------------------------------------------- /audits/100_correlated_token_oracles_quantstamp_20240412.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/100_correlated_token_oracles_quantstamp_20240412.pdf -------------------------------------------------------------------------------- /audits/101_correlated_token_oracles_fairyproof_20240328.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/101_correlated_token_oracles_fairyproof_20240328.pdf -------------------------------------------------------------------------------- /audits/110_sfrxETHOracle_certik_20240517.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/110_sfrxETHOracle_certik_20240517.pdf -------------------------------------------------------------------------------- /audits/111_sfrxETHOracle_quantstamp_20240530.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/111_sfrxETHOracle_quantstamp_20240530.pdf -------------------------------------------------------------------------------- /audits/116_WeETHAccountantOracle_certik_20240823.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/116_WeETHAccountantOracle_certik_20240823.pdf -------------------------------------------------------------------------------- /audits/119_pendleOracleUpdate_certik_20241226.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/119_pendleOracleUpdate_certik_20241226.pdf -------------------------------------------------------------------------------- /audits/123_erc4626Oracle_certik_20250206.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/123_erc4626Oracle_certik_20250206.pdf -------------------------------------------------------------------------------- /audits/124_oracles_certik_20250225.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/124_oracles_certik_20250225.pdf -------------------------------------------------------------------------------- /audits/128_AsBNBOracle_certik_20250320.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/audits/128_AsBNBOracle_certik_20250320.pdf -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ["@commitlint/config-conventional"], 3 | ignores: [commit => commit.includes("[skip ci]"), commit => commit.includes("Merge pull request")], 4 | "type-enum": [2, "always", ["build", "chore", "ci", "docs", "feat", "fix", "refactor", "test"]], 5 | }; 6 | -------------------------------------------------------------------------------- /contracts/interfaces/FeedRegistryInterface.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity ^0.8.25; 3 | 4 | interface FeedRegistryInterface { 5 | function latestRoundDataByName( 6 | string memory base, 7 | string memory quote 8 | ) 9 | external 10 | view 11 | returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); 12 | 13 | function decimalsByName(string memory base, string memory quote) external view returns (uint8); 14 | } 15 | -------------------------------------------------------------------------------- /contracts/interfaces/IAccountant.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | interface IAccountant { 5 | function getRateSafe() external view returns (uint256); 6 | } 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IAnkrBNB.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | interface IAnkrBNB { 5 | function sharesToBonds(uint256 amount) external view returns (uint256); 6 | function decimals() external view returns (uint8); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/interfaces/IAsBNB.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | interface IAsBNB { 5 | function minter() external view returns (address); 6 | function decimals() external view returns (uint8); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/interfaces/IAsBNBMinter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | interface IAsBNBMinter { 5 | function convertToTokens(uint256 amount) external view returns (uint256); 6 | } 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC4626.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | interface IERC4626 { 5 | function convertToAssets(uint256 shares) external view returns (uint256); 6 | function decimals() external view returns (uint8); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/interfaces/IEtherFiLiquidityPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | interface IEtherFiLiquidityPool { 5 | function amountForShare(uint256 _share) external view returns (uint256); 6 | } 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IPStakePool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | interface IPStakePool { 5 | struct Data { 6 | uint256 totalWei; 7 | uint256 poolTokenSupply; 8 | } 9 | 10 | /** 11 | * @dev The current exchange rate for converting stkBNB to BNB. 12 | */ 13 | function exchangeRate() external view returns (Data memory); 14 | } 15 | -------------------------------------------------------------------------------- /contracts/interfaces/IPendlePtOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | interface IPendlePtOracle { 5 | function getPtToAssetRate(address market, uint32 duration) external view returns (uint256); 6 | 7 | function getPtToSyRate(address market, uint32 duration) external view returns (uint256); 8 | 9 | function getOracleState( 10 | address market, 11 | uint32 duration 12 | ) 13 | external 14 | view 15 | returns (bool increaseCardinalityRequired, uint16 cardinalityRequired, bool oldestObservationSatisfied); 16 | } 17 | -------------------------------------------------------------------------------- /contracts/interfaces/ISFrax.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | interface ISFrax { 5 | function convertToAssets(uint256 shares) external view returns (uint256); 6 | function decimals() external view returns (uint8); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/interfaces/ISfrxEthFraxOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | interface ISfrxEthFraxOracle { 5 | function getPrices() external view returns (bool _isbadData, uint256 _priceLow, uint256 _priceHigh); 6 | } 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IStETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity ^0.8.25; 3 | 4 | interface IStETH { 5 | function getPooledEthByShares(uint256 _sharesAmount) external view returns (uint256); 6 | function decimals() external view returns (uint8); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/interfaces/IStaderStakeManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | interface IStaderStakeManager { 5 | function convertBnbXToBnb(uint256 _amount) external view returns (uint256); 6 | } 7 | -------------------------------------------------------------------------------- /contracts/interfaces/ISynclubStakeManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | interface ISynclubStakeManager { 5 | function convertSnBnbToBnb(uint256 _amount) external view returns (uint256); 6 | } 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IWBETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | interface IWBETH { 5 | function exchangeRate() external view returns (uint256); 6 | function decimals() external view returns (uint8); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/interfaces/IZkETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity ^0.8.25; 3 | 4 | interface IZkETH { 5 | function LSTPerToken() external view returns (uint256); 6 | function decimals() external view returns (uint8); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/interfaces/OracleInterface.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity ^0.8.25; 3 | 4 | interface OracleInterface { 5 | function getPrice(address asset) external view returns (uint256); 6 | } 7 | 8 | interface ResilientOracleInterface is OracleInterface { 9 | function updatePrice(address vToken) external; 10 | 11 | function updateAssetPrice(address asset) external; 12 | 13 | function getUnderlyingPrice(address vToken) external view returns (uint256); 14 | } 15 | 16 | interface TwapInterface is OracleInterface { 17 | function updateTwap(address asset) external returns (uint256); 18 | } 19 | 20 | interface BoundValidatorInterface { 21 | function validatePriceWithAnchorPrice( 22 | address asset, 23 | uint256 reporterPrice, 24 | uint256 anchorPrice 25 | ) external view returns (bool); 26 | } 27 | -------------------------------------------------------------------------------- /contracts/interfaces/PublicResolverInterface.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | // SPDX-FileCopyrightText: 2022 Venus 3 | pragma solidity ^0.8.25; 4 | 5 | interface PublicResolverInterface { 6 | function addr(bytes32 node) external view returns (address payable); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/interfaces/SIDRegistryInterface.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | // SPDX-FileCopyrightText: 2022 Venus 3 | pragma solidity ^0.8.25; 4 | 5 | interface SIDRegistryInterface { 6 | function resolver(bytes32 node) external view returns (address); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/interfaces/VBep20Interface.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity ^0.8.25; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; 5 | 6 | interface VBep20Interface is IERC20Metadata { 7 | /** 8 | * @notice Underlying asset for this VToken 9 | */ 10 | function underlying() external view returns (address); 11 | } 12 | -------------------------------------------------------------------------------- /contracts/oracles/AnkrBNBOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { IAnkrBNB } from "../interfaces/IAnkrBNB.sol"; 5 | import { CorrelatedTokenOracle } from "./common/CorrelatedTokenOracle.sol"; 6 | import { EXP_SCALE } from "@venusprotocol/solidity-utilities/contracts/constants.sol"; 7 | 8 | /** 9 | * @title AnkrBNBOracle 10 | * @author Venus 11 | * @notice This oracle fetches the price of ankrBNB asset 12 | */ 13 | contract AnkrBNBOracle is CorrelatedTokenOracle { 14 | /// @notice This is used as token address of BNB on BSC 15 | address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB; 16 | 17 | /// @notice Constructor for the implementation contract. 18 | /// @custom:oz-upgrades-unsafe-allow constructor 19 | constructor( 20 | address ankrBNB, 21 | address resilientOracle 22 | ) CorrelatedTokenOracle(ankrBNB, NATIVE_TOKEN_ADDR, resilientOracle) {} 23 | 24 | /** 25 | * @notice Fetches the amount of BNB for 1 ankrBNB 26 | * @return amount The amount of BNB for ankrBNB 27 | */ 28 | function _getUnderlyingAmount() internal view override returns (uint256) { 29 | return IAnkrBNB(CORRELATED_TOKEN).sharesToBonds(EXP_SCALE); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts/oracles/AsBNBOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { IAsBNB } from "../interfaces/IAsBNB.sol"; 5 | import { IAsBNBMinter } from "../interfaces/IAsBNBMinter.sol"; 6 | import { EXP_SCALE } from "@venusprotocol/solidity-utilities/contracts/constants.sol"; 7 | import { CorrelatedTokenOracle } from "./common/CorrelatedTokenOracle.sol"; 8 | 9 | /** 10 | * @title asBNBOracle 11 | * @author Venus 12 | * @notice This oracle fetches the price of asBNB asset 13 | */ 14 | contract AsBNBOracle is CorrelatedTokenOracle { 15 | /// @notice Constructor for the implementation contract. 16 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 17 | constructor( 18 | address asBNB, 19 | address slisBNB, 20 | address resilientOracle 21 | ) CorrelatedTokenOracle(asBNB, slisBNB, resilientOracle) {} 22 | 23 | /** 24 | * @notice Fetches the amount of slisBNB for 1 asBNB 25 | * @return price The amount of slisBNB for asBNB 26 | */ 27 | function _getUnderlyingAmount() internal view override returns (uint256) { 28 | IAsBNBMinter minter = IAsBNBMinter(IAsBNB(CORRELATED_TOKEN).minter()); 29 | return minter.convertToTokens(EXP_SCALE); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts/oracles/BNBxOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { IStaderStakeManager } from "../interfaces/IStaderStakeManager.sol"; 5 | import { ensureNonzeroAddress } from "@venusprotocol/solidity-utilities/contracts/validators.sol"; 6 | import { EXP_SCALE } from "@venusprotocol/solidity-utilities/contracts/constants.sol"; 7 | import { CorrelatedTokenOracle } from "./common/CorrelatedTokenOracle.sol"; 8 | 9 | /** 10 | * @title BNBxOracle 11 | * @author Venus 12 | * @notice This oracle fetches the price of BNBx asset 13 | */ 14 | contract BNBxOracle is CorrelatedTokenOracle { 15 | /// @notice This is used as token address of BNB on BSC 16 | address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB; 17 | 18 | /// @notice Address of StakeManager 19 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 20 | IStaderStakeManager public immutable STAKE_MANAGER; 21 | 22 | /// @notice Constructor for the implementation contract. 23 | /// @custom:oz-upgrades-unsafe-allow constructor 24 | constructor( 25 | address stakeManager, 26 | address bnbx, 27 | address resilientOracle 28 | ) CorrelatedTokenOracle(bnbx, NATIVE_TOKEN_ADDR, resilientOracle) { 29 | ensureNonzeroAddress(stakeManager); 30 | STAKE_MANAGER = IStaderStakeManager(stakeManager); 31 | } 32 | 33 | /** 34 | * @notice Fetches the amount of BNB for 1 BNBx 35 | * @return price The amount of BNB for BNBx 36 | */ 37 | function _getUnderlyingAmount() internal view override returns (uint256) { 38 | return STAKE_MANAGER.convertBnbXToBnb(EXP_SCALE); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /contracts/oracles/ERC4626Oracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { IERC4626 } from "../interfaces/IERC4626.sol"; 5 | import { CorrelatedTokenOracle } from "./common/CorrelatedTokenOracle.sol"; 6 | 7 | /** 8 | * @title ERC4626Oracle 9 | * @author Venus 10 | * @notice This oracle fetches the price of ERC4626 tokens 11 | */ 12 | contract ERC4626Oracle is CorrelatedTokenOracle { 13 | uint256 public immutable ONE_CORRELATED_TOKEN; 14 | 15 | /// @notice Constructor for the implementation contract. 16 | /// @custom:oz-upgrades-unsafe-allow constructor 17 | constructor( 18 | address correlatedToken, 19 | address underlyingToken, 20 | address resilientOracle 21 | ) CorrelatedTokenOracle(correlatedToken, underlyingToken, resilientOracle) { 22 | ONE_CORRELATED_TOKEN = 10 ** IERC4626(correlatedToken).decimals(); 23 | } 24 | 25 | /** 26 | * @notice Fetches the amount of underlying token for 1 correlated token 27 | * @return amount The amount of underlying token for correlated token 28 | */ 29 | function _getUnderlyingAmount() internal view override returns (uint256) { 30 | return IERC4626(CORRELATED_TOKEN).convertToAssets(ONE_CORRELATED_TOKEN); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /contracts/oracles/EtherfiAccountantOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { CorrelatedTokenOracle } from "./common/CorrelatedTokenOracle.sol"; 5 | import { IAccountant } from "../interfaces/IAccountant.sol"; 6 | import { ensureNonzeroAddress } from "@venusprotocol/solidity-utilities/contracts/validators.sol"; 7 | 8 | /** 9 | * @title EtherfiAccountantOracle 10 | * @author Venus 11 | * @notice This oracle fetches the price of any Ether.fi asset that uses 12 | * Accountant contracts to derive the underlying price 13 | */ 14 | contract EtherfiAccountantOracle is CorrelatedTokenOracle { 15 | /// @notice Address of Accountant 16 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 17 | IAccountant public immutable ACCOUNTANT; 18 | 19 | /// @notice Constructor for the implementation contract. 20 | /// @custom:oz-upgrades-unsafe-allow constructor 21 | constructor( 22 | address accountant, 23 | address correlatedToken, 24 | address underlyingToken, 25 | address resilientOracle 26 | ) CorrelatedTokenOracle(correlatedToken, underlyingToken, resilientOracle) { 27 | ensureNonzeroAddress(accountant); 28 | ACCOUNTANT = IAccountant(accountant); 29 | } 30 | 31 | /** 32 | * @notice Fetches the conversion rate from the ACCOUNTANT contract 33 | * @return amount Amount of WBTC 34 | */ 35 | function _getUnderlyingAmount() internal view override returns (uint256) { 36 | return ACCOUNTANT.getRateSafe(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /contracts/oracles/OneJumpOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { CorrelatedTokenOracle } from "./common/CorrelatedTokenOracle.sol"; 5 | import { ensureNonzeroAddress } from "@venusprotocol/solidity-utilities/contracts/validators.sol"; 6 | import { OracleInterface } from "../interfaces/OracleInterface.sol"; 7 | import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; 8 | 9 | /** 10 | * @title OneJumpOracle 11 | * @author Venus 12 | * @notice This oracle fetches the price of an asset in through an intermediate asset 13 | */ 14 | contract OneJumpOracle is CorrelatedTokenOracle { 15 | /// @notice Address of the intermediate oracle 16 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 17 | OracleInterface public immutable INTERMEDIATE_ORACLE; 18 | 19 | /// @notice Constructor for the implementation contract. 20 | /// @custom:oz-upgrades-unsafe-allow constructor 21 | constructor( 22 | address correlatedToken, 23 | address underlyingToken, 24 | address resilientOracle, 25 | address intermediateOracle 26 | ) CorrelatedTokenOracle(correlatedToken, underlyingToken, resilientOracle) { 27 | ensureNonzeroAddress(intermediateOracle); 28 | INTERMEDIATE_ORACLE = OracleInterface(intermediateOracle); 29 | } 30 | 31 | /** 32 | * @notice Fetches the amount of the underlying token for 1 correlated token, using the intermediate oracle 33 | * @return amount The amount of the underlying token for 1 correlated token scaled by the underlying token decimals 34 | */ 35 | function _getUnderlyingAmount() internal view override returns (uint256) { 36 | uint256 underlyingDecimals = IERC20Metadata(UNDERLYING_TOKEN).decimals(); 37 | uint256 correlatedDecimals = IERC20Metadata(CORRELATED_TOKEN).decimals(); 38 | 39 | uint256 underlyingAmount = INTERMEDIATE_ORACLE.getPrice(CORRELATED_TOKEN); 40 | 41 | return (underlyingAmount * (10 ** correlatedDecimals)) / (10 ** (36 - underlyingDecimals)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /contracts/oracles/SFraxOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { ISFrax } from "../interfaces/ISFrax.sol"; 5 | import { CorrelatedTokenOracle } from "./common/CorrelatedTokenOracle.sol"; 6 | import { EXP_SCALE } from "@venusprotocol/solidity-utilities/contracts/constants.sol"; 7 | 8 | /** 9 | * @title SFraxOracle 10 | * @author Venus 11 | * @notice This oracle fetches the price of sFrax 12 | */ 13 | contract SFraxOracle is CorrelatedTokenOracle { 14 | /// @notice Constructor for the implementation contract. 15 | /// @custom:oz-upgrades-unsafe-allow constructor 16 | constructor( 17 | address sFrax, 18 | address frax, 19 | address resilientOracle 20 | ) CorrelatedTokenOracle(sFrax, frax, resilientOracle) {} 21 | 22 | /** 23 | * @notice Fetches the amount of FRAX for 1 sFrax 24 | * @return amount The amount of FRAX for sFrax 25 | */ 26 | function _getUnderlyingAmount() internal view override returns (uint256) { 27 | return ISFrax(CORRELATED_TOKEN).convertToAssets(EXP_SCALE); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /contracts/oracles/SequencerChainlinkOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.25; 3 | 4 | import { ChainlinkOracle } from "./ChainlinkOracle.sol"; 5 | import { AggregatorV3Interface } from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; 6 | 7 | /** 8 | @title Sequencer Chain Link Oracle 9 | @notice Oracle to fetch price using chainlink oracles on L2s with sequencer 10 | */ 11 | contract SequencerChainlinkOracle is ChainlinkOracle { 12 | /// @notice L2 Sequencer feed 13 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 14 | AggregatorV3Interface public immutable sequencer; 15 | 16 | /// @notice L2 Sequencer grace period 17 | uint256 public constant GRACE_PERIOD_TIME = 3600; 18 | 19 | /** 20 | @notice Contract constructor 21 | @param _sequencer L2 sequencer 22 | @custom:oz-upgrades-unsafe-allow constructor 23 | */ 24 | constructor(AggregatorV3Interface _sequencer) ChainlinkOracle() { 25 | require(address(_sequencer) != address(0), "zero address"); 26 | 27 | sequencer = _sequencer; 28 | } 29 | 30 | /// @inheritdoc ChainlinkOracle 31 | function getPrice(address asset) public view override returns (uint) { 32 | if (!isSequencerActive()) revert("L2 sequencer unavailable"); 33 | return super.getPrice(asset); 34 | } 35 | 36 | function isSequencerActive() internal view returns (bool) { 37 | // answer from oracle is a variable with a value of either 1 or 0 38 | // 0: The sequencer is up 39 | // 1: The sequencer is down 40 | // startedAt: This timestamp indicates when the sequencer changed status 41 | (, int256 answer, uint256 startedAt, , ) = sequencer.latestRoundData(); 42 | if (block.timestamp - startedAt <= GRACE_PERIOD_TIME || answer == 1) return false; 43 | return true; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /contracts/oracles/SlisBNBOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { ISynclubStakeManager } from "../interfaces/ISynclubStakeManager.sol"; 5 | import { ensureNonzeroAddress } from "@venusprotocol/solidity-utilities/contracts/validators.sol"; 6 | import { CorrelatedTokenOracle } from "./common/CorrelatedTokenOracle.sol"; 7 | import { EXP_SCALE } from "@venusprotocol/solidity-utilities/contracts/constants.sol"; 8 | 9 | /** 10 | * @title SlisBNBOracle 11 | * @author Venus 12 | * @notice This oracle fetches the price of slisBNB asset 13 | */ 14 | contract SlisBNBOracle is CorrelatedTokenOracle { 15 | /// @notice This is used as token address of BNB on BSC 16 | address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB; 17 | 18 | /// @notice Address of StakeManager 19 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 20 | ISynclubStakeManager public immutable STAKE_MANAGER; 21 | 22 | /// @notice Constructor for the implementation contract. 23 | /// @custom:oz-upgrades-unsafe-allow constructor 24 | constructor( 25 | address stakeManager, 26 | address slisBNB, 27 | address resilientOracle 28 | ) CorrelatedTokenOracle(slisBNB, NATIVE_TOKEN_ADDR, resilientOracle) { 29 | ensureNonzeroAddress(stakeManager); 30 | STAKE_MANAGER = ISynclubStakeManager(stakeManager); 31 | } 32 | 33 | /** 34 | * @notice Fetches the amount of BNB for 1 slisBNB 35 | * @return amount The amount of BNB for slisBNB 36 | */ 37 | function _getUnderlyingAmount() internal view override returns (uint256) { 38 | return STAKE_MANAGER.convertSnBnbToBnb(EXP_SCALE); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /contracts/oracles/StkBNBOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { IPStakePool } from "../interfaces/IPStakePool.sol"; 5 | import { ensureNonzeroAddress } from "@venusprotocol/solidity-utilities/contracts/validators.sol"; 6 | import { EXP_SCALE } from "@venusprotocol/solidity-utilities/contracts/constants.sol"; 7 | import { CorrelatedTokenOracle } from "./common/CorrelatedTokenOracle.sol"; 8 | 9 | /** 10 | * @title StkBNBOracle 11 | * @author Venus 12 | * @notice This oracle fetches the price of stkBNB asset 13 | */ 14 | contract StkBNBOracle is CorrelatedTokenOracle { 15 | /// @notice This is used as token address of BNB on BSC 16 | address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB; 17 | 18 | /// @notice Address of StakePool 19 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 20 | IPStakePool public immutable STAKE_POOL; 21 | 22 | /// @notice Thrown if the pool token supply is zero 23 | error PoolTokenSupplyIsZero(); 24 | 25 | /// @notice Constructor for the implementation contract. 26 | /// @custom:oz-upgrades-unsafe-allow constructor 27 | constructor( 28 | address stakePool, 29 | address stkBNB, 30 | address resilientOracle 31 | ) CorrelatedTokenOracle(stkBNB, NATIVE_TOKEN_ADDR, resilientOracle) { 32 | ensureNonzeroAddress(stakePool); 33 | STAKE_POOL = IPStakePool(stakePool); 34 | } 35 | 36 | /** 37 | * @notice Fetches the amount of BNB for 1 stkBNB 38 | * @return price The amount of BNB for stkBNB 39 | */ 40 | function _getUnderlyingAmount() internal view override returns (uint256) { 41 | IPStakePool.Data memory exchangeRateData = STAKE_POOL.exchangeRate(); 42 | 43 | if (exchangeRateData.poolTokenSupply == 0) { 44 | revert PoolTokenSupplyIsZero(); 45 | } 46 | 47 | return (exchangeRateData.totalWei * EXP_SCALE) / exchangeRateData.poolTokenSupply; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /contracts/oracles/WBETHOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { IWBETH } from "../interfaces/IWBETH.sol"; 5 | import { CorrelatedTokenOracle } from "./common/CorrelatedTokenOracle.sol"; 6 | 7 | /** 8 | * @title WBETHOracle 9 | * @author Venus 10 | * @notice This oracle fetches the price of wBETH asset 11 | */ 12 | contract WBETHOracle is CorrelatedTokenOracle { 13 | /// @notice Constructor for the implementation contract. 14 | /// @custom:oz-upgrades-unsafe-allow constructor 15 | constructor( 16 | address wbeth, 17 | address eth, 18 | address resilientOracle 19 | ) CorrelatedTokenOracle(wbeth, eth, resilientOracle) {} 20 | 21 | /** 22 | * @notice Fetches the amount of ETH for 1 wBETH 23 | * @return amount The amount of ETH for wBETH 24 | */ 25 | function _getUnderlyingAmount() internal view override returns (uint256) { 26 | return IWBETH(CORRELATED_TOKEN).exchangeRate(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /contracts/oracles/WeETHAccountantOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { CorrelatedTokenOracle } from "./common/CorrelatedTokenOracle.sol"; 5 | import { IAccountant } from "../interfaces/IAccountant.sol"; 6 | import { ensureNonzeroAddress } from "@venusprotocol/solidity-utilities/contracts/validators.sol"; 7 | 8 | /** 9 | * @title WeETHAccountantOracle 10 | * @author Venus 11 | * @notice This oracle fetches the price of Ether.fi tokens based on an `Accountant` contract (i.e. weETHs and weETHk) 12 | */ 13 | contract WeETHAccountantOracle is CorrelatedTokenOracle { 14 | /// @notice Address of Accountant 15 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 16 | IAccountant public immutable ACCOUNTANT; 17 | 18 | /// @notice Constructor for the implementation contract. 19 | /// @custom:oz-upgrades-unsafe-allow constructor 20 | constructor( 21 | address accountant, 22 | address weethLRT, 23 | address weth, 24 | address resilientOracle 25 | ) CorrelatedTokenOracle(weethLRT, weth, resilientOracle) { 26 | ensureNonzeroAddress(accountant); 27 | ACCOUNTANT = IAccountant(accountant); 28 | } 29 | 30 | /** 31 | * @notice Gets the WETH for 1 weETH LRT 32 | * @return amount Amount of WETH 33 | */ 34 | function _getUnderlyingAmount() internal view override returns (uint256) { 35 | return ACCOUNTANT.getRateSafe(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /contracts/oracles/WeETHOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { CorrelatedTokenOracle } from "./common/CorrelatedTokenOracle.sol"; 5 | import { IEtherFiLiquidityPool } from "../interfaces/IEtherFiLiquidityPool.sol"; 6 | import { EXP_SCALE } from "@venusprotocol/solidity-utilities/contracts/constants.sol"; 7 | import { ensureNonzeroAddress } from "@venusprotocol/solidity-utilities/contracts/validators.sol"; 8 | 9 | /** 10 | * @title WeETHOracle 11 | * @author Venus 12 | * @notice This oracle fetches the price of weETH 13 | */ 14 | contract WeETHOracle is CorrelatedTokenOracle { 15 | /// @notice Address of Liqiudity pool 16 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 17 | IEtherFiLiquidityPool public immutable LIQUIDITY_POOL; 18 | 19 | /// @notice Constructor for the implementation contract. 20 | /// @custom:oz-upgrades-unsafe-allow constructor 21 | constructor( 22 | address liquidityPool, 23 | address weETH, 24 | address eETH, 25 | address resilientOracle 26 | ) CorrelatedTokenOracle(weETH, eETH, resilientOracle) { 27 | ensureNonzeroAddress(liquidityPool); 28 | LIQUIDITY_POOL = IEtherFiLiquidityPool(liquidityPool); 29 | } 30 | 31 | /** 32 | * @notice Gets the eETH for 1 weETH 33 | * @return amount Amount of eETH 34 | */ 35 | function _getUnderlyingAmount() internal view override returns (uint256) { 36 | return LIQUIDITY_POOL.amountForShare(EXP_SCALE); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /contracts/oracles/WstETHOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { OracleInterface } from "../interfaces/OracleInterface.sol"; 5 | import { IStETH } from "../interfaces/IStETH.sol"; 6 | import { ensureNonzeroAddress } from "@venusprotocol/solidity-utilities/contracts/validators.sol"; 7 | import { EXP_SCALE } from "@venusprotocol/solidity-utilities/contracts/constants.sol"; 8 | 9 | /** 10 | * @title WstETHOracle 11 | * @author Venus 12 | * @notice Depending on the equivalence flag price is either based on assumption that 1 stETH = 1 ETH 13 | * or the price of stETH/USD (secondary market price) is obtained from the oracle. 14 | */ 15 | contract WstETHOracle is OracleInterface { 16 | /// @notice A flag assuming 1:1 price equivalence between stETH/ETH 17 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 18 | bool public immutable ASSUME_STETH_ETH_EQUIVALENCE; 19 | 20 | /// @notice Address of stETH 21 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 22 | IStETH public immutable STETH; 23 | 24 | /// @notice Address of wstETH 25 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 26 | address public immutable WSTETH_ADDRESS; 27 | 28 | /// @notice Address of WETH 29 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 30 | address public immutable WETH_ADDRESS; 31 | 32 | /// @notice Address of Resilient Oracle 33 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 34 | OracleInterface public immutable RESILIENT_ORACLE; 35 | 36 | /// @notice Constructor for the implementation contract. 37 | /// @custom:oz-upgrades-unsafe-allow constructor 38 | constructor( 39 | address wstETHAddress, 40 | address wETHAddress, 41 | address stETHAddress, 42 | address resilientOracleAddress, 43 | bool assumeEquivalence 44 | ) { 45 | ensureNonzeroAddress(wstETHAddress); 46 | ensureNonzeroAddress(wETHAddress); 47 | ensureNonzeroAddress(stETHAddress); 48 | ensureNonzeroAddress(resilientOracleAddress); 49 | WSTETH_ADDRESS = wstETHAddress; 50 | WETH_ADDRESS = wETHAddress; 51 | STETH = IStETH(stETHAddress); 52 | RESILIENT_ORACLE = OracleInterface(resilientOracleAddress); 53 | ASSUME_STETH_ETH_EQUIVALENCE = assumeEquivalence; 54 | } 55 | 56 | /** 57 | * @notice Gets the USD price of wstETH asset 58 | * @dev Depending on the equivalence flag price is either based on assumption that 1 stETH = 1 ETH 59 | * or the price of stETH/USD (secondary market price) is obtained from the oracle 60 | * @param asset Address of wstETH 61 | * @return wstETH Price in USD scaled by 1e18 62 | */ 63 | function getPrice(address asset) public view returns (uint256) { 64 | if (asset != WSTETH_ADDRESS) revert("wrong wstETH address"); 65 | 66 | // get stETH amount for 1 wstETH scaled by 1e18 67 | uint256 stETHAmount = STETH.getPooledEthByShares(1 ether); 68 | 69 | // price is scaled 1e18 (oracle returns 36 - asset decimal scale) 70 | uint256 stETHUSDPrice = RESILIENT_ORACLE.getPrice(ASSUME_STETH_ETH_EQUIVALENCE ? WETH_ADDRESS : address(STETH)); 71 | 72 | // stETHAmount (for 1 wstETH) * stETHUSDPrice / 1e18 73 | return (stETHAmount * stETHUSDPrice) / EXP_SCALE; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /contracts/oracles/WstETHOracleV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { IStETH } from "../interfaces/IStETH.sol"; 5 | import { CorrelatedTokenOracle } from "./common/CorrelatedTokenOracle.sol"; 6 | import { EXP_SCALE } from "@venusprotocol/solidity-utilities/contracts/constants.sol"; 7 | 8 | /** 9 | * @title WstETHOracleV2 10 | * @author Venus 11 | * @notice This oracle fetches the price of wstETH 12 | */ 13 | contract WstETHOracleV2 is CorrelatedTokenOracle { 14 | /// @notice Constructor for the implementation contract. 15 | /// @custom:oz-upgrades-unsafe-allow constructor 16 | constructor( 17 | address wstETH, 18 | address stETH, 19 | address resilientOracle 20 | ) CorrelatedTokenOracle(wstETH, stETH, resilientOracle) {} 21 | 22 | /** 23 | * @notice Gets the stETH for 1 wstETH 24 | * @return amount Amount of stETH 25 | */ 26 | function _getUnderlyingAmount() internal view override returns (uint256) { 27 | return IStETH(UNDERLYING_TOKEN).getPooledEthByShares(EXP_SCALE); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /contracts/oracles/ZkETHOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { IZkETH } from "../interfaces/IZkETH.sol"; 5 | import { CorrelatedTokenOracle } from "./common/CorrelatedTokenOracle.sol"; 6 | 7 | /** 8 | * @title ZkETHOracle 9 | * @author Venus 10 | * @notice This oracle fetches the price of zkETH 11 | */ 12 | contract ZkETHOracle is CorrelatedTokenOracle { 13 | /// @notice Constructor for the implementation contract. 14 | /// @custom:oz-upgrades-unsafe-allow constructor 15 | constructor( 16 | address zkETH, 17 | address rzkETH, 18 | address resilientOracle 19 | ) CorrelatedTokenOracle(zkETH, rzkETH, resilientOracle) {} 20 | 21 | /** 22 | * @notice Gets the amount of rzkETH for 1 zkETH 23 | * @return amount Amount of rzkETH 24 | */ 25 | function _getUnderlyingAmount() internal view override returns (uint256) { 26 | return IZkETH(CORRELATED_TOKEN).LSTPerToken(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /contracts/oracles/common/CorrelatedTokenOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { OracleInterface } from "../../interfaces/OracleInterface.sol"; 5 | import { ensureNonzeroAddress } from "@venusprotocol/solidity-utilities/contracts/validators.sol"; 6 | import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; 7 | 8 | /** 9 | * @title CorrelatedTokenOracle 10 | * @notice This oracle fetches the price of a token that is correlated to another token. 11 | */ 12 | abstract contract CorrelatedTokenOracle is OracleInterface { 13 | /// @notice Address of the correlated token 14 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 15 | address public immutable CORRELATED_TOKEN; 16 | 17 | /// @notice Address of the underlying token 18 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 19 | address public immutable UNDERLYING_TOKEN; 20 | 21 | /// @notice Address of Resilient Oracle 22 | /// @custom:oz-upgrades-unsafe-allow state-variable-immutable 23 | OracleInterface public immutable RESILIENT_ORACLE; 24 | 25 | /// @notice Thrown if the token address is invalid 26 | error InvalidTokenAddress(); 27 | 28 | /// @notice Constructor for the implementation contract. 29 | /// @custom:oz-upgrades-unsafe-allow constructor 30 | constructor(address correlatedToken, address underlyingToken, address resilientOracle) { 31 | ensureNonzeroAddress(correlatedToken); 32 | ensureNonzeroAddress(underlyingToken); 33 | ensureNonzeroAddress(resilientOracle); 34 | CORRELATED_TOKEN = correlatedToken; 35 | UNDERLYING_TOKEN = underlyingToken; 36 | RESILIENT_ORACLE = OracleInterface(resilientOracle); 37 | } 38 | 39 | /** 40 | * @notice Fetches the price of the correlated token 41 | * @param asset Address of the correlated token 42 | * @return price The price of the correlated token in scaled decimal places 43 | */ 44 | function getPrice(address asset) external view override returns (uint256) { 45 | if (asset != CORRELATED_TOKEN) revert InvalidTokenAddress(); 46 | 47 | // get underlying token amount for 1 correlated token scaled by underlying token decimals 48 | uint256 underlyingAmount = _getUnderlyingAmount(); 49 | 50 | // oracle returns (36 - asset decimal) scaled price 51 | uint256 underlyingUSDPrice = RESILIENT_ORACLE.getPrice(UNDERLYING_TOKEN); 52 | 53 | IERC20Metadata token = IERC20Metadata(CORRELATED_TOKEN); 54 | uint256 decimals = token.decimals(); 55 | 56 | // underlyingAmount (for 1 correlated token) * underlyingUSDPrice / decimals(correlated token) 57 | return (underlyingAmount * underlyingUSDPrice) / (10 ** decimals); 58 | } 59 | 60 | /** 61 | * @notice Gets the underlying amount for correlated token 62 | * @return underlyingAmount Amount of underlying token 63 | */ 64 | function _getUnderlyingAmount() internal view virtual returns (uint256); 65 | } 66 | -------------------------------------------------------------------------------- /contracts/oracles/mocks/MockAccountant.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import "../../interfaces/IAccountant.sol"; 5 | import "@openzeppelin/contracts/access/Ownable.sol"; 6 | 7 | contract MockAccountant is IAccountant, Ownable { 8 | uint256 public rate; 9 | 10 | constructor() Ownable() {} 11 | 12 | function setRate(uint256 _rate) external onlyOwner { 13 | rate = _rate; 14 | } 15 | 16 | function getRateSafe() external view override returns (uint256) { 17 | return rate; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/oracles/mocks/MockBinanceFeedRegistry.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import "../../interfaces/FeedRegistryInterface.sol"; 5 | 6 | contract MockBinanceFeedRegistry is FeedRegistryInterface { 7 | mapping(string => uint256) public assetPrices; 8 | 9 | function setAssetPrice(string memory base, uint256 price) external { 10 | assetPrices[base] = price; 11 | } 12 | 13 | function latestRoundDataByName( 14 | string memory base, 15 | string memory quote 16 | ) 17 | external 18 | view 19 | override 20 | returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) 21 | { 22 | quote; 23 | return (0, int256(assetPrices[base]), 0, block.timestamp - 10, 0); 24 | } 25 | 26 | function decimalsByName(string memory base, string memory quote) external view override returns (uint8) { 27 | return 8; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /contracts/oracles/mocks/MockBinanceOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; 5 | import { OracleInterface } from "../../interfaces/OracleInterface.sol"; 6 | 7 | contract MockBinanceOracle is OwnableUpgradeable, OracleInterface { 8 | mapping(address => uint256) public assetPrices; 9 | 10 | constructor() {} 11 | 12 | function initialize() public initializer {} 13 | 14 | function setPrice(address asset, uint256 price) external { 15 | assetPrices[asset] = price; 16 | } 17 | 18 | function getPrice(address token) public view returns (uint256) { 19 | return assetPrices[token]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /contracts/oracles/mocks/MockChainlinkOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; 5 | import { OracleInterface } from "../../interfaces/OracleInterface.sol"; 6 | 7 | contract MockChainlinkOracle is OwnableUpgradeable, OracleInterface { 8 | mapping(address => uint256) public assetPrices; 9 | 10 | //set price in 6 decimal precision 11 | constructor() {} 12 | 13 | function initialize() public initializer { 14 | __Ownable_init(); 15 | } 16 | 17 | function setPrice(address asset, uint256 price) external { 18 | assetPrices[asset] = price; 19 | } 20 | 21 | //https://compound.finance/docs/prices 22 | function getPrice(address token) public view returns (uint256) { 23 | return assetPrices[token]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /contracts/oracles/mocks/MockPendlePtOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import "../../interfaces/IPendlePtOracle.sol"; 5 | import "@openzeppelin/contracts/access/Ownable.sol"; 6 | 7 | contract MockPendlePtOracle is IPendlePtOracle, Ownable { 8 | mapping(address => mapping(uint32 => uint256)) public ptToAssetRate; 9 | mapping(address => mapping(uint32 => uint256)) public ptToSyRate; 10 | 11 | constructor() Ownable() {} 12 | 13 | function setPtToAssetRate(address market, uint32 duration, uint256 rate) external onlyOwner { 14 | ptToAssetRate[market][duration] = rate; 15 | } 16 | 17 | function setPtToSyRate(address market, uint32 duration, uint256 rate) external onlyOwner { 18 | ptToSyRate[market][duration] = rate; 19 | } 20 | 21 | function getPtToAssetRate(address market, uint32 duration) external view returns (uint256) { 22 | return ptToAssetRate[market][duration]; 23 | } 24 | 25 | function getPtToSyRate(address market, uint32 duration) external view returns (uint256) { 26 | return ptToSyRate[market][duration]; 27 | } 28 | 29 | function getOracleState( 30 | address /* market */, 31 | uint32 /* duration */ 32 | ) 33 | external 34 | pure 35 | returns (bool increaseCardinalityRequired, uint16 cardinalityRequired, bool oldestObservationSatisfied) 36 | { 37 | return (false, 0, true); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /contracts/oracles/mocks/MockPythOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; 5 | import { IPyth } from "../PythOracle.sol"; 6 | import { OracleInterface } from "../../interfaces/OracleInterface.sol"; 7 | 8 | contract MockPythOracle is OwnableUpgradeable { 9 | mapping(address => uint256) public assetPrices; 10 | 11 | /// @notice the actual pyth oracle address fetch & store the prices 12 | IPyth public underlyingPythOracle; 13 | 14 | //set price in 6 decimal precision 15 | constructor() {} 16 | 17 | function initialize(address underlyingPythOracle_) public initializer { 18 | __Ownable_init(); 19 | if (underlyingPythOracle_ == address(0)) revert("pyth oracle cannot be zero address"); 20 | underlyingPythOracle = IPyth(underlyingPythOracle_); 21 | } 22 | 23 | function setPrice(address asset, uint256 price) external { 24 | assetPrices[asset] = price; 25 | } 26 | 27 | //https://compound.finance/docs/prices 28 | function getPrice(address token) public view returns (uint256) { 29 | return assetPrices[token]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts/oracles/mocks/MockSFrxEthFraxOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import "../../interfaces/ISfrxEthFraxOracle.sol"; 5 | import "@openzeppelin/contracts/access/Ownable.sol"; 6 | 7 | contract MockSfrxEthFraxOracle is ISfrxEthFraxOracle, Ownable { 8 | bool public isBadData; 9 | uint256 public priceLow; 10 | uint256 public priceHigh; 11 | 12 | constructor() Ownable() {} 13 | 14 | function setPrices(bool _isBadData, uint256 _priceLow, uint256 _priceHigh) external onlyOwner { 15 | isBadData = _isBadData; 16 | priceLow = _priceLow; 17 | priceHigh = _priceHigh; 18 | } 19 | 20 | function getPrices() external view override returns (bool, uint256, uint256) { 21 | return (isBadData, priceLow, priceHigh); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /contracts/test/BEP20Harness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 | 6 | contract BEP20Harness is ERC20 { 7 | uint8 public decimalsInternal = 18; 8 | 9 | constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) { 10 | decimalsInternal = decimals_; 11 | } 12 | 13 | function faucet(uint256 amount) external { 14 | _mint(msg.sender, amount); 15 | } 16 | 17 | function decimals() public view virtual override returns (uint8) { 18 | return decimalsInternal; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /contracts/test/MockAnkrBNB.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 7 | import { IAnkrBNB } from "../interfaces/IAnkrBNB.sol"; 8 | import "@openzeppelin/contracts/access/Ownable.sol"; 9 | 10 | contract MockAnkrBNB is ERC20, Ownable, IAnkrBNB { 11 | uint8 private immutable _decimals; 12 | uint256 public exchangeRate; 13 | 14 | constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) Ownable() { 15 | _decimals = decimals_; 16 | } 17 | 18 | function faucet(uint256 amount) external { 19 | _mint(msg.sender, amount); 20 | } 21 | 22 | function setSharesToBonds(uint256 rate) external onlyOwner { 23 | exchangeRate = rate; 24 | } 25 | 26 | function sharesToBonds(uint256 amount) external view override returns (uint256) { 27 | return (amount * exchangeRate) / (10 ** uint256(_decimals)); 28 | } 29 | 30 | function decimals() public view virtual override(ERC20, IAnkrBNB) returns (uint8) { 31 | return _decimals; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /contracts/test/MockAsBNB.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 7 | import { IAsBNB } from "../interfaces/IAsBNB.sol"; 8 | import "@openzeppelin/contracts/access/Ownable.sol"; 9 | 10 | contract MockAsBNB is ERC20, Ownable, IAsBNB { 11 | uint8 private immutable _decimals; 12 | address public minter; 13 | 14 | constructor( 15 | string memory name_, 16 | string memory symbol_, 17 | uint8 decimals_, 18 | address minter_ 19 | ) ERC20(name_, symbol_) Ownable() { 20 | _decimals = decimals_; 21 | minter = minter_; 22 | } 23 | 24 | function faucet(uint256 amount) external { 25 | _mint(msg.sender, amount); 26 | } 27 | 28 | function setMinter(address minter_) external onlyOwner { 29 | minter = minter_; 30 | } 31 | 32 | function decimals() public view virtual override(ERC20, IAsBNB) returns (uint8) { 33 | return _decimals; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /contracts/test/MockAsBNBMinter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import { IAsBNBMinter } from "../interfaces/IAsBNBMinter.sol"; 7 | 8 | contract MockAsBNBMinter is IAsBNBMinter { 9 | function convertToTokens(uint256 _amount) external pure override returns (uint256) { 10 | return _amount; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contracts/test/MockEtherFiLiquidityPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import "../interfaces/IEtherFiLiquidityPool.sol"; 5 | import "@openzeppelin/contracts/access/Ownable.sol"; 6 | 7 | contract MockEtherFiLiquidityPool is IEtherFiLiquidityPool, Ownable { 8 | /// @notice The amount of eETH per weETH scaled by 1e18 9 | uint256 public amountPerShare; 10 | 11 | constructor() Ownable() {} 12 | 13 | function setAmountPerShare(uint256 _amountPerShare) external onlyOwner { 14 | amountPerShare = _amountPerShare; 15 | } 16 | 17 | function amountForShare(uint256 _share) external view override returns (uint256) { 18 | return (_share * amountPerShare) / 1e18; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /contracts/test/MockSFrax.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 7 | import { ISFrax } from "../interfaces/ISFrax.sol"; 8 | import "@openzeppelin/contracts/access/Ownable.sol"; 9 | 10 | contract MockSFrax is ERC20, Ownable, ISFrax { 11 | uint8 private immutable _decimals; 12 | uint256 public exchangeRate; 13 | 14 | constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) Ownable() { 15 | _decimals = decimals_; 16 | } 17 | 18 | function faucet(uint256 amount) external { 19 | _mint(msg.sender, amount); 20 | } 21 | 22 | function setRate(uint256 rate) external onlyOwner { 23 | exchangeRate = rate; 24 | } 25 | 26 | function convertToAssets(uint256 shares) external view override returns (uint256) { 27 | return (shares * exchangeRate) / (10 ** uint256(_decimals)); 28 | } 29 | 30 | function decimals() public view virtual override(ERC20, ISFrax) returns (uint8) { 31 | return _decimals; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /contracts/test/MockSimpleOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import "../interfaces/OracleInterface.sol"; 5 | 6 | contract MockSimpleOracle is OracleInterface { 7 | mapping(address => uint256) public prices; 8 | 9 | constructor() { 10 | // 11 | } 12 | 13 | function getUnderlyingPrice(address vToken) external view returns (uint256) { 14 | return prices[vToken]; 15 | } 16 | 17 | function getPrice(address asset) external view returns (uint256) { 18 | return prices[asset]; 19 | } 20 | 21 | function setPrice(address vToken, uint256 price) public { 22 | prices[vToken] = price; 23 | } 24 | } 25 | 26 | contract MockBoundValidator is BoundValidatorInterface { 27 | mapping(address => bool) public validateResults; 28 | bool public twapUpdated; 29 | 30 | constructor() { 31 | // 32 | } 33 | 34 | function validatePriceWithAnchorPrice( 35 | address vToken, 36 | uint256 reporterPrice, 37 | uint256 anchorPrice 38 | ) external view returns (bool) { 39 | return validateResults[vToken]; 40 | } 41 | 42 | function validateAssetPriceWithAnchorPrice( 43 | address asset, 44 | uint256 reporterPrice, 45 | uint256 anchorPrice 46 | ) external view returns (bool) { 47 | return validateResults[asset]; 48 | } 49 | 50 | function setValidateResult(address token, bool pass) public { 51 | validateResults[token] = pass; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /contracts/test/MockV3Aggregator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV2V3Interface.sol"; 5 | 6 | /** 7 | * @title MockV3Aggregator 8 | * @notice Based on the FluxAggregator contract 9 | * @notice Use this contract when you need to test 10 | * other contract's ability to read data from an 11 | * aggregator contract, but how the aggregator got 12 | * its answer is unimportant 13 | */ 14 | contract MockV3Aggregator is AggregatorV2V3Interface { 15 | uint256 public constant version = 0; 16 | 17 | uint8 public decimals; 18 | int256 public latestAnswer; 19 | uint256 public latestTimestamp; 20 | uint256 public latestRound; 21 | 22 | mapping(uint256 => int256) public getAnswer; 23 | mapping(uint256 => uint256) public getTimestamp; 24 | mapping(uint256 => uint256) private getStartedAt; 25 | 26 | constructor(uint8 _decimals, int256 _initialAnswer) { 27 | decimals = _decimals; 28 | updateAnswer(_initialAnswer); 29 | } 30 | 31 | function getRoundData( 32 | uint80 _roundId 33 | ) 34 | external 35 | view 36 | returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) 37 | { 38 | return (_roundId, getAnswer[_roundId], getStartedAt[_roundId], getTimestamp[_roundId], _roundId); 39 | } 40 | 41 | function latestRoundData() 42 | external 43 | view 44 | returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) 45 | { 46 | return ( 47 | uint80(latestRound), 48 | getAnswer[latestRound], 49 | getStartedAt[latestRound], 50 | getTimestamp[latestRound], 51 | uint80(latestRound) 52 | ); 53 | } 54 | 55 | function description() external pure returns (string memory) { 56 | return "v0.6/tests/MockV3Aggregator.sol"; 57 | } 58 | 59 | function updateAnswer(int256 _answer) public { 60 | latestAnswer = _answer; 61 | latestTimestamp = block.timestamp; 62 | latestRound++; 63 | getAnswer[latestRound] = _answer; 64 | getTimestamp[latestRound] = block.timestamp; 65 | getStartedAt[latestRound] = block.timestamp; 66 | } 67 | 68 | function updateRoundData(uint80 _roundId, int256 _answer, uint256 _timestamp, uint256 _startedAt) public { 69 | latestRound = _roundId; 70 | latestAnswer = _answer; 71 | latestTimestamp = _timestamp; 72 | getAnswer[latestRound] = _answer; 73 | getTimestamp[latestRound] = _timestamp; 74 | getStartedAt[latestRound] = _startedAt; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /contracts/test/MockWBETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 7 | import { IWBETH } from "../interfaces/IWBETH.sol"; 8 | import "@openzeppelin/contracts/access/Ownable.sol"; 9 | 10 | contract MockWBETH is ERC20, Ownable, IWBETH { 11 | uint8 private immutable _decimals; 12 | uint256 public override exchangeRate; 13 | 14 | constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) Ownable() { 15 | _decimals = decimals_; 16 | } 17 | 18 | function faucet(uint256 amount) external { 19 | _mint(msg.sender, amount); 20 | } 21 | 22 | function setExchangeRate(uint256 rate) external onlyOwner { 23 | exchangeRate = rate; 24 | } 25 | 26 | function decimals() public view virtual override(ERC20, IWBETH) returns (uint8) { 27 | return _decimals; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /contracts/test/PancakePairHarness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | // a library for performing various math operations 5 | 6 | library Math { 7 | function min(uint256 x, uint256 y) internal pure returns (uint256 z) { 8 | z = x < y ? x : y; 9 | } 10 | 11 | // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) 12 | function sqrt(uint256 y) internal pure returns (uint256 z) { 13 | if (y > 3) { 14 | z = y; 15 | uint256 x = y / 2 + 1; 16 | while (x < z) { 17 | z = x; 18 | x = (y / x + x) / 2; 19 | } 20 | } else if (y != 0) { 21 | z = 1; 22 | } 23 | } 24 | } 25 | 26 | // range: [0, 2**112 - 1] 27 | // resolution: 1 / 2**112 28 | 29 | library UQ112x112 { 30 | //solhint-disable-next-line state-visibility 31 | uint224 constant Q112 = 2 ** 112; 32 | 33 | // encode a uint112 as a UQ112x112 34 | function encode(uint112 y) internal pure returns (uint224 z) { 35 | z = uint224(y) * Q112; // never overflows 36 | } 37 | 38 | // divide a UQ112x112 by a uint112, returning a UQ112x112 39 | function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) { 40 | z = x / uint224(y); 41 | } 42 | } 43 | 44 | contract PancakePairHarness { 45 | using UQ112x112 for uint224; 46 | 47 | address public token0; 48 | address public token1; 49 | 50 | uint112 private reserve0; // uses single storage slot, accessible via getReserves 51 | uint112 private reserve1; // uses single storage slot, accessible via getReserves 52 | uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves 53 | 54 | uint256 public price0CumulativeLast; 55 | uint256 public price1CumulativeLast; 56 | uint256 public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event 57 | 58 | // called once by the factory at time of deployment 59 | function initialize(address _token0, address _token1) external { 60 | token0 = _token0; 61 | token1 = _token1; 62 | } 63 | 64 | // update reserves and, on the first call per block, price accumulators 65 | function update(uint256 balance0, uint256 balance1, uint112 _reserve0, uint112 _reserve1) external { 66 | require(balance0 <= type(uint112).max && balance1 <= type(uint112).max, "PancakeV2: OVERFLOW"); 67 | uint32 blockTimestamp = uint32(block.timestamp % 2 ** 32); 68 | unchecked { 69 | uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired 70 | if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) { 71 | // * never overflows, and + overflow is desired 72 | price0CumulativeLast += uint256(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed; 73 | price1CumulativeLast += uint256(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed; 74 | } 75 | } 76 | reserve0 = uint112(balance0); 77 | reserve1 = uint112(balance1); 78 | blockTimestampLast = blockTimestamp; 79 | } 80 | 81 | function currentBlockTimestamp() external view returns (uint32) { 82 | return uint32(block.timestamp % 2 ** 32); 83 | } 84 | 85 | function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) { 86 | _reserve0 = reserve0; 87 | _reserve1 = reserve1; 88 | _blockTimestampLast = blockTimestampLast; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /contracts/test/VBEP20Harness.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | pragma solidity 0.8.25; 3 | 4 | import "./BEP20Harness.sol"; 5 | 6 | contract VBEP20Harness is BEP20Harness { 7 | /** 8 | * @notice Underlying asset for this VToken 9 | */ 10 | address public underlying; 11 | 12 | constructor( 13 | string memory name_, 14 | string memory symbol_, 15 | uint8 decimals, 16 | address underlying_ 17 | ) BEP20Harness(name_, symbol_, decimals) { 18 | underlying = underlying_; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /deploy/10-deploy-rsETH-oracles.ts: -------------------------------------------------------------------------------- 1 | import hre from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | const proxyOwnerAddress = ADDRESSES[network.name].timelock; 11 | const { WETH, rsETH } = ADDRESSES[network.name]; 12 | 13 | const redStoneOracle = await hre.ethers.getContract("RedStoneOracle"); 14 | const resilientOracle = await hre.ethers.getContract("ResilientOracle"); 15 | const chainlinkOracle = await hre.ethers.getContract("ChainlinkOracle"); 16 | 17 | await deploy("rsETHOneJumpRedStoneOracle", { 18 | contract: "OneJumpOracle", 19 | from: deployer, 20 | log: true, 21 | deterministicDeployment: false, 22 | args: [rsETH, WETH, resilientOracle.address, redStoneOracle.address], 23 | proxy: { 24 | owner: proxyOwnerAddress, 25 | proxyContract: "OptimizedTransparentProxy", 26 | }, 27 | skipIfAlreadyDeployed: true, 28 | }); 29 | 30 | await deploy("rsETHOneJumpChainlinkOracle", { 31 | contract: "OneJumpOracle", 32 | from: deployer, 33 | log: true, 34 | deterministicDeployment: false, 35 | args: [rsETH, WETH, resilientOracle.address, chainlinkOracle.address], 36 | proxy: { 37 | owner: proxyOwnerAddress, 38 | proxyContract: "OptimizedTransparentProxy", 39 | }, 40 | skipIfAlreadyDeployed: true, 41 | }); 42 | }; 43 | 44 | func.skip = async () => hre.network.name !== "ethereum" && hre.network.name !== "sepolia"; 45 | func.tags = ["rsETHOneJumpOracles"]; 46 | export default func; 47 | -------------------------------------------------------------------------------- /deploy/11-dependencies-sfrxeth-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) => { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | 11 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 12 | 13 | await deploy("MockSfrxEthFraxOracle", { 14 | contract: "MockSfrxEthFraxOracle", 15 | from: deployer, 16 | log: true, 17 | autoMine: true, 18 | skipIfAlreadyDeployed: true, 19 | args: [], 20 | }); 21 | 22 | const mockSfrxEthFraxOracle = await ethers.getContract("MockSfrxEthFraxOracle"); 23 | 24 | if ((await mockSfrxEthFraxOracle.owner()) === deployer) { 25 | await mockSfrxEthFraxOracle.transferOwnership(proxyOwnerAddress); 26 | } 27 | }; 28 | 29 | export default func; 30 | func.tags = ["sFraxETHOracle"]; 31 | func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "sepolia"; 32 | -------------------------------------------------------------------------------- /deploy/11-deploy-sfrxeth-oracle.ts: -------------------------------------------------------------------------------- 1 | import { parseUnits } from "ethers/lib/utils"; 2 | import { ethers } from "hardhat"; 3 | import { DeployFunction } from "hardhat-deploy/dist/types"; 4 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 5 | 6 | import { ADDRESSES } from "../helpers/deploymentConfig"; 7 | 8 | const func: DeployFunction = async ({ 9 | getNamedAccounts, 10 | deployments, 11 | network, 12 | artifacts, 13 | }: HardhatRuntimeEnvironment) => { 14 | const { deploy } = deployments; 15 | const { deployer } = await getNamedAccounts(); 16 | 17 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 18 | const defaultProxyAdmin = await artifacts.readArtifact( 19 | "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol:ProxyAdmin", 20 | ); 21 | const { sfrxETH, SfrxEthFraxOracle, acm } = ADDRESSES[network.name]; 22 | const maxAllowedPriceDifference = parseUnits("1.14", 18); 23 | 24 | await deploy("SFrxETHOracle", { 25 | contract: "SFrxETHOracle", 26 | from: deployer, 27 | log: true, 28 | deterministicDeployment: false, 29 | args: [SfrxEthFraxOracle || (await ethers.getContract("MockSfrxEthFraxOracle")).address, sfrxETH], 30 | proxy: { 31 | owner: proxyOwnerAddress, 32 | proxyContract: "OptimizedTransparentProxy", 33 | execute: { 34 | methodName: "initialize", 35 | args: [acm, maxAllowedPriceDifference], 36 | }, 37 | viaAdminContract: { 38 | name: "DefaultProxyAdmin", 39 | artifact: defaultProxyAdmin, 40 | }, 41 | }, 42 | skipIfAlreadyDeployed: true, 43 | }); 44 | 45 | const sfrxETHOracle = await ethers.getContract("SFrxETHOracle"); 46 | 47 | if ((await sfrxETHOracle.owner()) === deployer) { 48 | await sfrxETHOracle.transferOwnership(proxyOwnerAddress); 49 | } 50 | }; 51 | 52 | export default func; 53 | func.tags = ["sFraxETHOracle"]; 54 | func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "ethereum" && hre.network.name !== "sepolia"; 55 | -------------------------------------------------------------------------------- /deploy/11-setup-sfrxeth-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async ({ getNamedAccounts, network }: HardhatRuntimeEnvironment) => { 8 | const { deployer } = await getNamedAccounts(); 9 | 10 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 11 | 12 | const sfrxETHOracle = await ethers.getContract("SFrxETHOracle"); 13 | 14 | if ((await sfrxETHOracle.owner()) === deployer) { 15 | await sfrxETHOracle.transferOwnership(proxyOwnerAddress); 16 | } 17 | }; 18 | 19 | export default func; 20 | func.id = "sFraxETHOracle-setup"; 21 | func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "ethereum"; 22 | -------------------------------------------------------------------------------- /deploy/12-deploy-ezETH-oracles.ts: -------------------------------------------------------------------------------- 1 | import hre from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | const proxyOwnerAddress = ADDRESSES[network.name].timelock; 11 | const { ezETH, WETH } = ADDRESSES[network.name]; 12 | 13 | const redStoneOracle = await hre.ethers.getContract("RedStoneOracle"); 14 | const resilientOracle = await hre.ethers.getContract("ResilientOracle"); 15 | const chainlinkOracle = await hre.ethers.getContract("ChainlinkOracle"); 16 | 17 | await deploy("ezETHOneJumpRedStoneOracle", { 18 | contract: "OneJumpOracle", 19 | from: deployer, 20 | log: true, 21 | deterministicDeployment: false, 22 | args: [ezETH, WETH, resilientOracle.address, redStoneOracle.address], 23 | proxy: { 24 | owner: proxyOwnerAddress, 25 | proxyContract: "OptimizedTransparentProxy", 26 | }, 27 | skipIfAlreadyDeployed: true, 28 | }); 29 | 30 | await deploy("ezETHOneJumpChainlinkOracle", { 31 | contract: "OneJumpOracle", 32 | from: deployer, 33 | log: true, 34 | deterministicDeployment: false, 35 | args: [ezETH, WETH, resilientOracle.address, chainlinkOracle.address], 36 | proxy: { 37 | owner: proxyOwnerAddress, 38 | proxyContract: "OptimizedTransparentProxy", 39 | }, 40 | skipIfAlreadyDeployed: true, 41 | }); 42 | }; 43 | 44 | func.skip = async () => hre.network.name !== "ethereum" && hre.network.name !== "sepolia"; 45 | func.tags = ["ezETHOneJumpOracles"]; 46 | export default func; 47 | -------------------------------------------------------------------------------- /deploy/13-dependencies-weETHs-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) => { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | 11 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 12 | 13 | await deploy("MockAccountant_weETHs", { 14 | from: deployer, 15 | contract: "MockAccountant", 16 | args: [], 17 | log: true, 18 | autoMine: true, 19 | skipIfAlreadyDeployed: true, 20 | }); 21 | 22 | const mockAccountant = await ethers.getContract("MockAccountant_weETHs"); 23 | await mockAccountant.transferOwnership(proxyOwnerAddress); 24 | }; 25 | 26 | export default func; 27 | func.tags = ["WeETHAccountantOracle_weETHs"]; 28 | func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "sepolia"; 29 | -------------------------------------------------------------------------------- /deploy/13-deploy-weETHs-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async ({ 8 | getNamedAccounts, 9 | deployments, 10 | network, 11 | artifacts, 12 | }: HardhatRuntimeEnvironment) => { 13 | const { deploy } = deployments; 14 | const { deployer } = await getNamedAccounts(); 15 | 16 | const resilientOracle = await ethers.getContract("ResilientOracle"); 17 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 18 | const defaultProxyAdmin = await artifacts.readArtifact( 19 | "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol:ProxyAdmin", 20 | ); 21 | let { weETHs_Accountant } = ADDRESSES[network.name]; 22 | const { weETHs, WETH } = ADDRESSES[network.name]; 23 | 24 | weETHs_Accountant = weETHs_Accountant || (await ethers.getContract("MockAccountant_weETHs")).address; 25 | 26 | await deploy("WeETHAccountantOracle_weETHs", { 27 | contract: "WeETHAccountantOracle", 28 | from: deployer, 29 | log: true, 30 | deterministicDeployment: false, 31 | args: [weETHs_Accountant, weETHs, WETH, resilientOracle.address], 32 | proxy: { 33 | owner: proxyOwnerAddress, 34 | proxyContract: "OptimizedTransparentUpgradeableProxy", 35 | viaAdminContract: { 36 | name: "DefaultProxyAdmin", 37 | artifact: defaultProxyAdmin, 38 | }, 39 | }, 40 | skipIfAlreadyDeployed: true, 41 | }); 42 | }; 43 | 44 | export default func; 45 | func.tags = ["WeETHAccountantOracle_weETHs"]; 46 | func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "ethereum" && hre.network.name !== "sepolia"; 47 | -------------------------------------------------------------------------------- /deploy/13-deploy-wstETH-weETH-oracles.ts: -------------------------------------------------------------------------------- 1 | import hre from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ 8 | getNamedAccounts, 9 | deployments, 10 | network, 11 | artifacts, 12 | }: HardhatRuntimeEnvironment) { 13 | const { deploy } = deployments; 14 | const { deployer } = await getNamedAccounts(); 15 | const proxyOwnerAddress = ADDRESSES[network.name].timelock; 16 | const { WETH, wstETH, weETH } = ADDRESSES[network.name]; 17 | 18 | const resilientOracle = await hre.ethers.getContract("ResilientOracle"); 19 | 20 | let chainlinkOracle; 21 | if (hre.network.name === "arbitrumone") { 22 | chainlinkOracle = await hre.ethers.getContract("SequencerChainlinkOracle"); 23 | } else { 24 | chainlinkOracle = await hre.ethers.getContract("ChainlinkOracle"); 25 | } 26 | 27 | const defaultProxyAdmin = await artifacts.readArtifact( 28 | "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol:ProxyAdmin", 29 | ); 30 | 31 | const commonParams = { 32 | from: deployer, 33 | log: true, 34 | deterministicDeployment: false, 35 | proxy: { 36 | owner: proxyOwnerAddress, 37 | proxyContract: "OptimizedTransparentUpgradeableProxy", 38 | viaAdminContract: { 39 | name: "DefaultProxyAdmin", 40 | artifact: defaultProxyAdmin, 41 | }, 42 | }, 43 | skipIfAlreadyDeployed: true, 44 | waitConfirmations: 1, 45 | }; 46 | 47 | await deploy("wstETHOneJumpChainlinkOracle", { 48 | contract: "OneJumpOracle", 49 | args: [wstETH, WETH, resilientOracle.address, chainlinkOracle.address], 50 | ...commonParams, 51 | }); 52 | 53 | await deploy("weETHOneJumpChainlinkOracle", { 54 | contract: "OneJumpOracle", 55 | args: [weETH, WETH, resilientOracle.address, chainlinkOracle.address], 56 | ...commonParams, 57 | }); 58 | 59 | if (["bscmainnet", "bsctestnet"].includes(hre.network.name)) { 60 | const redstoneOracle = await hre.ethers.getContract("RedStoneOracle"); 61 | 62 | await deploy("wstETHOneJumpRedstoneOracle", { 63 | contract: "OneJumpOracle", 64 | args: [wstETH, WETH, resilientOracle.address, redstoneOracle.address], 65 | ...commonParams, 66 | }); 67 | 68 | await deploy("weETHOneJumpRedstoneOracle", { 69 | contract: "OneJumpOracle", 70 | args: [weETH, WETH, resilientOracle.address, redstoneOracle.address], 71 | ...commonParams, 72 | }); 73 | } 74 | }; 75 | 76 | func.skip = async () => !["bscmainnet", "bsctestnet", "arbitrumone", "arbitrumsepolia"].includes(hre.network.name); 77 | func.tags = ["wstETH_weETH_OneJumpOracles"]; 78 | export default func; 79 | -------------------------------------------------------------------------------- /deploy/14-dependencies-eBTC-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) => { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | 11 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 12 | 13 | await deploy("MockAccountant_eBTC", { 14 | from: deployer, 15 | contract: "MockAccountant", 16 | args: [], 17 | log: true, 18 | autoMine: true, 19 | skipIfAlreadyDeployed: true, 20 | }); 21 | 22 | const mockAccountant = await ethers.getContract("MockAccountant_eBTC"); 23 | await mockAccountant.transferOwnership(proxyOwnerAddress); 24 | }; 25 | 26 | export default func; 27 | func.tags = ["eBTCAccountantOracle"]; 28 | func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "sepolia"; 29 | -------------------------------------------------------------------------------- /deploy/14-deploy-ERC4626Oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | const { sUSDe, USDe } = ADDRESSES[network.name]; 11 | 12 | const resilientOracle = await ethers.getContract("ResilientOracle"); 13 | await deploy("sUSDe_ERC4626Oracle", { 14 | contract: "ERC4626Oracle", 15 | from: deployer, 16 | log: true, 17 | deterministicDeployment: false, 18 | args: [sUSDe, USDe, resilientOracle.address], 19 | }); 20 | }; 21 | 22 | func.tags = ["deploy-ERC4626-oracle"]; 23 | func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "ethereum" && hre.network.name !== "sepolia"; 24 | 25 | export default func; 26 | -------------------------------------------------------------------------------- /deploy/14-deploy-eBTC-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async ({ 8 | getNamedAccounts, 9 | deployments, 10 | network, 11 | artifacts, 12 | }: HardhatRuntimeEnvironment) => { 13 | const { deploy } = deployments; 14 | const { deployer } = await getNamedAccounts(); 15 | 16 | const resilientOracle = await ethers.getContract("ResilientOracle"); 17 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 18 | const defaultProxyAdmin = await artifacts.readArtifact( 19 | "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol:ProxyAdmin", 20 | ); 21 | let { eBTC_Accountant } = ADDRESSES[network.name]; 22 | const { WBTC, eBTC } = ADDRESSES[network.name]; 23 | 24 | eBTC_Accountant = eBTC_Accountant || (await ethers.getContract("MockAccountant_eBTC")).address; 25 | 26 | await deploy("eBTCAccountantOracle", { 27 | contract: "EtherfiAccountantOracle", 28 | from: deployer, 29 | log: true, 30 | deterministicDeployment: false, 31 | args: [eBTC_Accountant, eBTC, WBTC, resilientOracle.address], 32 | proxy: { 33 | owner: proxyOwnerAddress, 34 | proxyContract: "OptimizedTransparentUpgradeableProxy", 35 | viaAdminContract: { 36 | name: "DefaultProxyAdmin", 37 | artifact: defaultProxyAdmin, 38 | }, 39 | }, 40 | skipIfAlreadyDeployed: true, 41 | }); 42 | }; 43 | 44 | export default func; 45 | func.tags = ["eBTCAccountantOracle"]; 46 | func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "ethereum" && hre.network.name !== "sepolia"; 47 | -------------------------------------------------------------------------------- /deploy/14-deploy-pufETH-oracle.ts: -------------------------------------------------------------------------------- 1 | import hre from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | const proxyOwnerAddress = ADDRESSES[network.name].timelock; 11 | const { pufETH, WETH } = ADDRESSES[network.name]; 12 | 13 | const redStoneOracle = await hre.ethers.getContract("RedStoneOracle"); 14 | const resilientOracle = await hre.ethers.getContract("ResilientOracle"); 15 | 16 | await deploy("pufETHOneJumpRedStoneOracle", { 17 | contract: "OneJumpOracle", 18 | from: deployer, 19 | log: true, 20 | deterministicDeployment: false, 21 | args: [pufETH, WETH, resilientOracle.address, redStoneOracle.address], 22 | proxy: { 23 | owner: proxyOwnerAddress, 24 | proxyContract: "OptimizedTransparentProxy", 25 | }, 26 | skipIfAlreadyDeployed: true, 27 | }); 28 | }; 29 | 30 | func.skip = async () => hre.network.name !== "ethereum" && hre.network.name !== "sepolia"; 31 | func.tags = ["pufETHOneJumpRedStoneOracle"]; 32 | export default func; 33 | -------------------------------------------------------------------------------- /deploy/15-deploy-lbtc-oracle.ts: -------------------------------------------------------------------------------- 1 | import hre from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | const proxyOwnerAddress = ADDRESSES[network.name].timelock; 11 | const { LBTC, WBTC } = ADDRESSES[network.name]; 12 | 13 | const redstoneOracle = await hre.ethers.getContract("RedStoneOracle"); 14 | const resilientOracle = await hre.ethers.getContract("ResilientOracle"); 15 | 16 | await deploy("LBTCOneJumpRedStoneOracle", { 17 | contract: "OneJumpOracle", 18 | from: deployer, 19 | log: true, 20 | deterministicDeployment: false, 21 | args: [LBTC, WBTC, resilientOracle.address, redstoneOracle.address], 22 | proxy: { 23 | owner: proxyOwnerAddress, 24 | proxyContract: "OptimizedTransparentProxy", 25 | }, 26 | skipIfAlreadyDeployed: true, 27 | }); 28 | }; 29 | 30 | func.skip = async () => hre.network.name !== "ethereum" && hre.network.name !== "sepolia"; 31 | func.tags = ["LBTCOneJumpRedStoneOracle"]; 32 | export default func; 33 | -------------------------------------------------------------------------------- /deploy/16-deploy-SolvBTC.BBN-pendle-oracles.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | import { isMainnet } from "../helpers/deploymentUtils"; 7 | 8 | enum PendleRateKind { 9 | PT_TO_ASSET = 0, 10 | PT_TO_SY = 1, 11 | } 12 | 13 | const func: DeployFunction = async ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) => { 14 | const { deploy } = deployments; 15 | const { deployer } = await getNamedAccounts(); 16 | 17 | const oracle = await ethers.getContract("ResilientOracle"); 18 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 19 | const redStoneOracle = await ethers.getContract("RedStoneOracle"); 20 | const resilientOracle = await ethers.getContract("ResilientOracle"); 21 | const addresses = ADDRESSES[network.name]; 22 | const ptOracleAddress = addresses.PTOracle || (await ethers.getContract("MockPendlePtOracle")).address; 23 | 24 | await deploy("SolvBTC.BBN_OneJumpRedStoneOracle", { 25 | contract: "OneJumpOracle", 26 | from: deployer, 27 | log: true, 28 | deterministicDeployment: false, 29 | args: [addresses["SolvBTC.BBN"], addresses.BTCB, resilientOracle.address, redStoneOracle.address], 30 | proxy: { 31 | owner: proxyOwnerAddress, 32 | proxyContract: "OptimizedTransparentProxy", 33 | }, 34 | skipIfAlreadyDeployed: true, 35 | }); 36 | 37 | await deploy("PendleOracle-PT-SolvBTC.BBN-27MAR2025", { 38 | contract: "PendleOracle", 39 | from: deployer, 40 | log: true, 41 | deterministicDeployment: false, 42 | args: [ 43 | addresses["PT-SolvBTC.BBN-27MAR2025_Market"] || "0x0000000000000000000000000000000000000001", 44 | ptOracleAddress, 45 | PendleRateKind.PT_TO_SY, 46 | addresses["PT-SolvBTC.BBN-27MAR2025"], 47 | addresses["SolvBTC.BBN"], 48 | oracle.address, 49 | 900, 50 | ], 51 | proxy: { 52 | owner: proxyOwnerAddress, 53 | proxyContract: "OptimizedTransparentUpgradeableProxy", 54 | }, 55 | skipIfAlreadyDeployed: true, 56 | }); 57 | 58 | if (isMainnet(network)) { 59 | const referenceOracle = await ethers.getContract("ReferenceOracle"); 60 | const { devMultisig } = addresses; 61 | await deploy("PendleOracle-PT-SolvBTC.BBN-27MAR2025_Reference_PtToAsset", { 62 | contract: "PendleOracle", 63 | from: deployer, 64 | log: true, 65 | deterministicDeployment: false, 66 | args: [ 67 | addresses["PT-SolvBTC.BBN-27MAR2025_Market"] || "0x0000000000000000000000000000000000000001", 68 | ptOracleAddress, 69 | PendleRateKind.PT_TO_ASSET, 70 | addresses["PT-SolvBTC.BBN-27MAR2025"], 71 | addresses.BTCB, 72 | referenceOracle.address, 73 | 900, 74 | ], 75 | proxy: { 76 | owner: devMultisig, 77 | proxyContract: "OptimizedTransparentUpgradeableProxy", 78 | viaAdminContract: { 79 | name: "DevProxyAdmin", 80 | }, 81 | }, 82 | skipIfAlreadyDeployed: true, 83 | }); 84 | } 85 | }; 86 | 87 | export default func; 88 | func.tags = ["PT-SolvBTC.BBN"]; 89 | func.skip = async (hre: HardhatRuntimeEnvironment) => 90 | hre.network.name !== "bsctestnet" && hre.network.name !== "bscmainnet"; 91 | -------------------------------------------------------------------------------- /deploy/17-deploy-wUSDM-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | const { wUSDM, USDM } = ADDRESSES[network.name]; 11 | 12 | const resilientOracle = await ethers.getContract("ResilientOracle"); 13 | await deploy("wUSDM_ERC4626Oracle", { 14 | contract: "ERC4626Oracle", 15 | from: deployer, 16 | log: true, 17 | deterministicDeployment: false, 18 | args: [wUSDM, USDM, resilientOracle.address], 19 | }); 20 | }; 21 | 22 | func.tags = ["wUSDM"]; 23 | func.skip = async (hre: HardhatRuntimeEnvironment) => 24 | hre.network.name !== "zksyncmainnet" && hre.network.name !== "zksyncsepolia"; 25 | 26 | export default func; 27 | -------------------------------------------------------------------------------- /deploy/18-deploy-sUSDC-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | const { sUSDS, USDS } = ADDRESSES[network.name]; 11 | 12 | const resilientOracle = await ethers.getContract("ResilientOracle"); 13 | await deploy("sUSDS_ERC4626Oracle", { 14 | contract: "ERC4626Oracle", 15 | from: deployer, 16 | log: true, 17 | deterministicDeployment: false, 18 | args: [sUSDS, USDS, resilientOracle.address], 19 | }); 20 | }; 21 | 22 | func.tags = ["sUSDS"]; 23 | func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "ethereum" && hre.network.name !== "sepolia"; 24 | 25 | export default func; 26 | -------------------------------------------------------------------------------- /deploy/18-deploy-wsuperOETHb-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | const { WETH, wsuperOETHb } = ADDRESSES[network.name]; 11 | 12 | const resilientOracle = await ethers.getContract("ResilientOracle"); 13 | await deploy("wsuperOETHb_ERC4626Oracle", { 14 | contract: "ERC4626Oracle", 15 | from: deployer, 16 | log: true, 17 | deterministicDeployment: false, 18 | args: [wsuperOETHb, WETH, resilientOracle.address], 19 | }); 20 | }; 21 | 22 | func.tags = ["wsuperOETHb"]; 23 | func.skip = async (hre: HardhatRuntimeEnvironment) => 24 | hre.network.name !== "basemainnet" && hre.network.name !== "basesepolia"; 25 | 26 | export default func; 27 | -------------------------------------------------------------------------------- /deploy/19-deploy-yearn-oracles.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | const { WETH, USDC, USDT, USDS, yvUSDC_1, yvUSDT_1, yvUSDS_1, yvWETH_1 } = ADDRESSES[network.name]; 11 | 12 | const resilientOracle = await ethers.getContract("ResilientOracle"); 13 | await deploy("yvUSDC-1_ERC4626Oracle", { 14 | contract: "ERC4626Oracle", 15 | from: deployer, 16 | log: true, 17 | deterministicDeployment: false, 18 | args: [yvUSDC_1, USDC, resilientOracle.address], 19 | }); 20 | 21 | await deploy("yvUSDT-1_ERC4626Oracle", { 22 | contract: "ERC4626Oracle", 23 | from: deployer, 24 | log: true, 25 | deterministicDeployment: false, 26 | args: [yvUSDT_1, USDT, resilientOracle.address], 27 | }); 28 | 29 | await deploy("yvUSDS-1_ERC4626Oracle", { 30 | contract: "ERC4626Oracle", 31 | from: deployer, 32 | log: true, 33 | deterministicDeployment: false, 34 | args: [yvUSDS_1, USDS, resilientOracle.address], 35 | }); 36 | 37 | await deploy("yvWETH-1_ERC4626Oracle", { 38 | contract: "ERC4626Oracle", 39 | from: deployer, 40 | log: true, 41 | deterministicDeployment: false, 42 | args: [yvWETH_1, WETH, resilientOracle.address], 43 | }); 44 | }; 45 | 46 | func.tags = ["yearn"]; 47 | func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "ethereum" && hre.network.name !== "sepolia"; 48 | 49 | export default func; 50 | -------------------------------------------------------------------------------- /deploy/2-deploy-binance-oracle.ts: -------------------------------------------------------------------------------- 1 | import hre from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | 11 | const accessControlManagerAddress = ADDRESSES[network.name].acm; 12 | const proxyOwnerAddress = ADDRESSES[network.name].timelock; 13 | const timelock = ADDRESSES[network.name].timeloc; 14 | 15 | const { sidRegistryAddress, feedRegistryAddress } = ADDRESSES[network.name]; 16 | 17 | // Skip if no sidRegistryAddress address in config 18 | if (sidRegistryAddress) { 19 | await deploy("BinanceOracle", { 20 | contract: "BinanceOracle", 21 | from: deployer, 22 | log: true, 23 | deterministicDeployment: false, 24 | args: [], 25 | proxy: { 26 | owner: proxyOwnerAddress, 27 | proxyContract: "OptimizedTransparentProxy", 28 | execute: { 29 | methodName: "initialize", 30 | args: [sidRegistryAddress, accessControlManagerAddress], 31 | }, 32 | }, 33 | }); 34 | const binanceOracle = await hre.ethers.getContract("BinanceOracle"); 35 | const binanceOracleOwner = await binanceOracle.owner(); 36 | 37 | if (sidRegistryAddress === "0x0000000000000000000000000000000000000000") { 38 | await binanceOracle.setFeedRegistryAddress(feedRegistryAddress); 39 | } 40 | 41 | if (binanceOracleOwner === deployer) { 42 | await binanceOracle.transferOwnership(timelock); 43 | console.log(`Ownership of BinanceOracle transfered from deployer to Timelock (${timelock})`); 44 | } 45 | } 46 | }; 47 | 48 | func.tags = ["deploy-binance-oracle"]; 49 | func.skip = async env => !env.network.live; 50 | 51 | export default func; 52 | -------------------------------------------------------------------------------- /deploy/2-deploy-pyth-oracle.ts: -------------------------------------------------------------------------------- 1 | import hre from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | 11 | const accessControlManagerAddress = ADDRESSES[network.name].acm; 12 | const proxyOwnerAddress = ADDRESSES[network.name].timelock; 13 | const { timelock, pythOracleAddress } = ADDRESSES[network.name]; 14 | 15 | // Skip if no pythOracle address in config 16 | if (pythOracleAddress) { 17 | await deploy("PythOracle", { 18 | contract: "PythOracle", 19 | from: deployer, 20 | log: true, 21 | deterministicDeployment: false, 22 | args: [], 23 | proxy: { 24 | owner: proxyOwnerAddress, 25 | proxyContract: "OptimizedTransparentProxy", 26 | execute: { 27 | methodName: "initialize", 28 | args: [pythOracleAddress, accessControlManagerAddress], 29 | }, 30 | }, 31 | }); 32 | 33 | const pythOracle = await hre.ethers.getContract("PythOracle"); 34 | const pythOracleOwner = await pythOracle.owner(); 35 | 36 | if (pythOracleOwner === deployer) { 37 | await pythOracle.transferOwnership(timelock); 38 | console.log(`Ownership of PythOracle transfered from deployer to Timelock (${timelock})`); 39 | } 40 | } 41 | }; 42 | func.tags = ["deploy-pyth-oracle"]; 43 | func.skip = async env => !env.network.live; 44 | 45 | export default func; 46 | -------------------------------------------------------------------------------- /deploy/2-deploy-redstone-oracle.ts: -------------------------------------------------------------------------------- 1 | import hre from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES, SEQUENCER } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 11 | const defaultProxyAdmin = await hre.artifacts.readArtifact( 12 | "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol:ProxyAdmin", 13 | ); 14 | 15 | const sequencer = SEQUENCER[network.name]; 16 | let contractName = "ChainlinkOracle"; 17 | if (sequencer !== undefined) contractName = "SequencerChainlinkOracle"; 18 | 19 | await deploy("RedStoneOracle", { 20 | contract: network.live ? contractName : "MockChainlinkOracle", 21 | from: deployer, 22 | log: true, 23 | deterministicDeployment: false, 24 | skipIfAlreadyDeployed: true, 25 | args: sequencer ? [sequencer] : [], 26 | proxy: { 27 | owner: proxyOwnerAddress, 28 | proxyContract: "OptimizedTransparentUpgradeableProxy", 29 | execute: { 30 | methodName: "initialize", 31 | args: network.live ? [ADDRESSES[network.name].acm] : [], 32 | }, 33 | viaAdminContract: { 34 | name: "DefaultProxyAdmin", 35 | artifact: defaultProxyAdmin, 36 | }, 37 | }, 38 | }); 39 | 40 | const redStoneOracle = await hre.ethers.getContract("RedStoneOracle"); 41 | const redStoneOracleOwner = await redStoneOracle.owner(); 42 | 43 | if (redStoneOracleOwner === deployer && network.live) { 44 | await redStoneOracle.transferOwnership(proxyOwnerAddress); 45 | console.log(`Ownership of RedstoneOracle transfered from deployer to Timelock (${proxyOwnerAddress})`); 46 | } 47 | }; 48 | 49 | func.tags = ["deploy-redstone"]; 50 | func.skip = async env => !env.network.live; 51 | export default func; 52 | -------------------------------------------------------------------------------- /deploy/2-deploy-reference-oracle.ts: -------------------------------------------------------------------------------- 1 | import hre from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | import { skipAllExcept } from "../helpers/deploymentUtils"; 7 | 8 | const func: DeployFunction = async function ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) { 9 | const { deploy } = deployments; 10 | const { deployer } = await getNamedAccounts(); 11 | 12 | const devMultisig = network.live ? ADDRESSES[network.name].devMultisig : deployer; 13 | const proxyAdminArtifact = await hre.artifacts.readArtifact( 14 | "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol:ProxyAdmin", 15 | ); 16 | 17 | const resilientOracle = await hre.ethers.getContract("ResilientOracle"); 18 | 19 | await deploy("ReferenceOracle", { 20 | contract: "ReferenceOracle", 21 | from: deployer, 22 | log: true, 23 | deterministicDeployment: false, 24 | skipIfAlreadyDeployed: true, 25 | args: [resilientOracle.address], 26 | proxy: { 27 | owner: devMultisig, 28 | proxyContract: "OptimizedTransparentUpgradeableProxy", 29 | execute: { 30 | methodName: "initialize", 31 | args: [], 32 | }, 33 | viaAdminContract: { 34 | name: "DevProxyAdmin", 35 | artifact: proxyAdminArtifact, 36 | }, 37 | }, 38 | }); 39 | 40 | const devProxyAdmin = await hre.ethers.getContract("DevProxyAdmin"); 41 | const devProxyAdminOwner = await devProxyAdmin.owner(); 42 | 43 | if (devProxyAdminOwner === deployer) { 44 | await devProxyAdmin.transferOwnership(devMultisig); 45 | console.log(`Ownership of DevProxyAdmin transfered from deployer to dev multisig (${devMultisig})`); 46 | } 47 | 48 | const referenceOracle = await hre.ethers.getContract("ReferenceOracle"); 49 | const referenceOracleOwner = await referenceOracle.owner(); 50 | 51 | if (referenceOracleOwner === deployer) { 52 | await referenceOracle.transferOwnership(devMultisig); 53 | console.log(`Ownership of ReferenceOracle transfered from deployer to dev multisig (${devMultisig})`); 54 | } 55 | }; 56 | 57 | export default func; 58 | func.skip = skipAllExcept(["bscmainnet", "ethereum"]); 59 | func.tags = ["reference"]; 60 | -------------------------------------------------------------------------------- /deploy/20-deploy-clisBNB-pendle-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | import { isMainnet } from "../helpers/deploymentUtils"; 7 | 8 | enum PendleRateKind { 9 | PT_TO_ASSET = 0, 10 | PT_TO_SY = 1, 11 | } 12 | 13 | const func: DeployFunction = async ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) => { 14 | const { deploy } = deployments; 15 | const { deployer } = await getNamedAccounts(); 16 | 17 | const oracle = await ethers.getContract("ResilientOracle"); 18 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 19 | const addresses = ADDRESSES[network.name]; 20 | const ptOracleAddress = addresses.PTOracle || (await ethers.getContract("MockPendlePtOracle")).address; 21 | 22 | await deploy("PendleOracle-PT-clisBNB-24APR2025", { 23 | contract: "PendleOracle", 24 | from: deployer, 25 | log: true, 26 | deterministicDeployment: false, 27 | args: [ 28 | addresses["PT-clisBNB-24APR2025_Market"] || "0x0000000000000000000000000000000000000002", 29 | ptOracleAddress, 30 | PendleRateKind.PT_TO_SY, 31 | addresses["PT-clisBNB-24APR2025"], 32 | addresses.slisBNB, 33 | oracle.address, 34 | 1800, 35 | ], 36 | proxy: { 37 | owner: proxyOwnerAddress, 38 | proxyContract: "OptimizedTransparentUpgradeableProxy", 39 | }, 40 | skipIfAlreadyDeployed: true, 41 | }); 42 | 43 | if (isMainnet(network)) { 44 | const referenceOracle = await ethers.getContract("ReferenceOracle"); 45 | const { devMultisig } = addresses; 46 | await deploy("PendleOracle-PT-clisBNB-24APR2025_Reference_PtToAsset", { 47 | contract: "PendleOracle", 48 | from: deployer, 49 | log: true, 50 | deterministicDeployment: false, 51 | args: [ 52 | addresses["PT-clisBNB-24APR2025_Market"] || "0x0000000000000000000000000000000000000002", 53 | ptOracleAddress, 54 | PendleRateKind.PT_TO_ASSET, 55 | addresses["PT-clisBNB-24APR2025"], 56 | addresses.WBNBAddress, 57 | referenceOracle.address, 58 | 1800, 59 | ], 60 | proxy: { 61 | owner: devMultisig, 62 | proxyContract: "OptimizedTransparentUpgradeableProxy", 63 | viaAdminContract: { 64 | name: "DevProxyAdmin", 65 | }, 66 | }, 67 | skipIfAlreadyDeployed: true, 68 | }); 69 | } 70 | }; 71 | 72 | export default func; 73 | func.tags = ["PT-clisBNB"]; 74 | func.skip = async (hre: HardhatRuntimeEnvironment) => 75 | hre.network.name !== "bsctestnet" && hre.network.name !== "bscmainnet"; 76 | -------------------------------------------------------------------------------- /deploy/20-deploy-wstETH-one-jump-oracle.ts: -------------------------------------------------------------------------------- 1 | import hre from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ 8 | getNamedAccounts, 9 | deployments, 10 | network, 11 | artifacts, 12 | }: HardhatRuntimeEnvironment) { 13 | const { deploy } = deployments; 14 | const { deployer } = await getNamedAccounts(); 15 | if (!deployer) { 16 | throw new Error("Deployer address is not defined. Ensure deployer is set in namedAccounts."); 17 | } 18 | const proxyOwnerAddress = ADDRESSES[network.name].timelock; 19 | const { WETH, wstETH } = ADDRESSES[network.name]; 20 | 21 | const resilientOracle = await hre.ethers.getContract("ResilientOracle"); 22 | 23 | const chainlinkOracle = await hre.ethers.getContract("ChainlinkOracle"); 24 | 25 | const defaultProxyAdmin = await artifacts.readArtifact( 26 | "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol:ProxyAdmin", 27 | ); 28 | 29 | const commonParams = { 30 | from: deployer, 31 | log: true, 32 | deterministicDeployment: false, 33 | proxy: { 34 | owner: proxyOwnerAddress, 35 | proxyContract: "OptimizedTransparentUpgradeableProxy", 36 | viaAdminContract: { 37 | name: "DefaultProxyAdmin", 38 | artifact: defaultProxyAdmin, 39 | }, 40 | }, 41 | skipIfAlreadyDeployed: true, 42 | waitConfirmations: 1, 43 | }; 44 | 45 | await deploy("wstETHOneJumpChainlinkOracle", { 46 | contract: "OneJumpOracle", 47 | args: [wstETH, WETH, resilientOracle.address, chainlinkOracle.address], 48 | ...commonParams, 49 | }); 50 | }; 51 | 52 | func.skip = async () => !["basemainnet", "basetestnet", "zksyncsepolia", "zksyncmainnet"].includes(hre.network.name); 53 | func.tags = ["wstETH_OneJumpOracle"]; 54 | export default func; 55 | -------------------------------------------------------------------------------- /deploy/20-deploy-zkETH-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async ({ 8 | getNamedAccounts, 9 | deployments, 10 | network, 11 | artifacts, 12 | }: HardhatRuntimeEnvironment) => { 13 | const { deploy } = deployments; 14 | const { deployer } = await getNamedAccounts(); 15 | 16 | const oracle = await ethers.getContract("ResilientOracle"); 17 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 18 | 19 | const { zkETH, WETH } = ADDRESSES[network.name]; 20 | const defaultProxyAdmin = await artifacts.readArtifact( 21 | "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol:ProxyAdmin", 22 | ); 23 | await deploy("ZkETHOracle", { 24 | from: deployer, 25 | log: true, 26 | deterministicDeployment: false, 27 | args: [zkETH, WETH, oracle.address], 28 | proxy: { 29 | owner: proxyOwnerAddress, 30 | proxyContract: "OptimizedTransparentUpgradeableProxy", 31 | viaAdminContract: { 32 | name: "DefaultProxyAdmin", 33 | artifact: defaultProxyAdmin, 34 | }, 35 | }, 36 | skipIfAlreadyDeployed: true, 37 | }); 38 | }; 39 | 40 | export default func; 41 | func.tags = ["zkETH"]; 42 | func.skip = async (hre: HardhatRuntimeEnvironment) => 43 | hre.network.name !== "zksyncmainnet" && hre.network.name !== "zksyncsepolia"; 44 | -------------------------------------------------------------------------------- /deploy/21-deploy-asBNB-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async ({ 8 | getNamedAccounts, 9 | deployments, 10 | network, 11 | artifacts, 12 | }: HardhatRuntimeEnvironment) => { 13 | const { deploy } = deployments; 14 | const { deployer } = await getNamedAccounts(); 15 | 16 | const oracle = await ethers.getContract("ResilientOracle"); 17 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 18 | 19 | const { asBNB, slisBNB } = ADDRESSES[network.name]; 20 | const defaultProxyAdmin = await artifacts.readArtifact( 21 | "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol:ProxyAdmin", 22 | ); 23 | 24 | // Deploy dependencies for testnet 25 | if (network.name === "bsctestnet") { 26 | await deploy("MockAsBNBMinter", { 27 | from: deployer, 28 | contract: "MockAsBNBMinter", 29 | args: [], 30 | log: true, 31 | autoMine: true, 32 | skipIfAlreadyDeployed: true, 33 | }); 34 | 35 | const minter = await ethers.getContract("MockAsBNBMinter"); 36 | 37 | await deploy("MockAsBNB", { 38 | from: deployer, 39 | contract: "MockAsBNB", 40 | args: ["Astherus BNB", "asBNB", 18, minter.address], 41 | log: true, 42 | autoMine: true, 43 | skipIfAlreadyDeployed: true, 44 | }); 45 | } 46 | 47 | console.log("args", asBNB, slisBNB, oracle.address); 48 | await deploy("AsBNBOracle", { 49 | from: deployer, 50 | log: true, 51 | deterministicDeployment: false, 52 | args: [asBNB, slisBNB, oracle.address], 53 | proxy: { 54 | owner: proxyOwnerAddress, 55 | proxyContract: "OptimizedTransparentUpgradeableProxy", 56 | viaAdminContract: { 57 | name: "DefaultProxyAdmin", 58 | artifact: defaultProxyAdmin, 59 | }, 60 | }, 61 | skipIfAlreadyDeployed: true, 62 | }); 63 | }; 64 | 65 | export default func; 66 | func.tags = ["asBnbOracle"]; 67 | func.skip = async (hre: HardhatRuntimeEnvironment) => 68 | hre.network.name !== "bsctestnet" && hre.network.name !== "bscmainnet"; 69 | -------------------------------------------------------------------------------- /deploy/23-deploy-xSolvBTC.ts: -------------------------------------------------------------------------------- 1 | import hre from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | const proxyOwnerAddress = ADDRESSES[network.name].timelock; 11 | const { xSolvBTC, SolvBTC } = ADDRESSES[network.name]; 12 | 13 | const redstoneOracle = await hre.ethers.getContract("RedStoneOracle"); 14 | const resilientOracle = await hre.ethers.getContract("ResilientOracle"); 15 | 16 | await deploy("xSolvBTCOneJumpRedStoneOracle", { 17 | contract: "OneJumpOracle", 18 | from: deployer, 19 | log: true, 20 | deterministicDeployment: false, 21 | args: [xSolvBTC, SolvBTC, resilientOracle.address, redstoneOracle.address], 22 | proxy: { 23 | owner: proxyOwnerAddress, 24 | proxyContract: "OptimizedTransparentProxy", 25 | }, 26 | skipIfAlreadyDeployed: true, 27 | }); 28 | }; 29 | 30 | func.skip = async () => hre.network.name !== "bscmainnet" && hre.network.name !== "bsctestnet"; 31 | func.tags = ["xSolvBTC"]; 32 | export default func; 33 | -------------------------------------------------------------------------------- /deploy/3-configure-feeds.ts: -------------------------------------------------------------------------------- 1 | import hre from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { Oracles, assets, getOraclesData } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ network, deployments, getNamedAccounts }: HardhatRuntimeEnvironment) { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | 11 | const resilientOracle = await hre.ethers.getContract("ResilientOracle"); 12 | 13 | const oraclesData: Oracles = await getOraclesData(); 14 | 15 | for (const asset of assets[network.name]) { 16 | const { oracle } = asset; 17 | console.log(`Configuring ${asset.token}`); 18 | 19 | await deploy(`Mock${asset.token}`, { 20 | from: deployer, 21 | log: true, 22 | deterministicDeployment: false, 23 | args: [`Mock${asset.token}`, `Mock${asset.token}`, 18], 24 | autoMine: true, 25 | contract: "BEP20Harness", 26 | }); 27 | 28 | const mock = await hre.ethers.getContract(`Mock${asset.token}`); 29 | 30 | console.log(`Configuring resilient oracle for ${asset.token}`); 31 | let tx = await resilientOracle.setTokenConfig({ 32 | asset: mock.address, 33 | oracles: oraclesData[oracle].oracles, 34 | enableFlagsForOracles: oraclesData[oracle].enableFlagsForOracles, 35 | }); 36 | 37 | await tx.wait(1); 38 | 39 | console.log(`Configuring ${oracle} oracle for ${asset.token}`); 40 | tx = await oraclesData[oracle].underlyingOracle?.setPrice(mock.address, asset.price); 41 | await tx.wait(1); 42 | } 43 | }; 44 | 45 | export default func; 46 | func.tags = ["configure"]; 47 | func.skip = async env => env.network.live; 48 | -------------------------------------------------------------------------------- /deploy/3-resilient-oracle-imp-update.ts: -------------------------------------------------------------------------------- 1 | import hre from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async function ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) { 8 | const { deploy, catchUnknownSigner } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | 11 | const { vBNBAddress } = ADDRESSES[network.name]; 12 | const { VAIAddress } = ADDRESSES[network.name]; 13 | 14 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 15 | const boundValidator = await hre.ethers.getContract("BoundValidator"); 16 | 17 | const defaultProxyAdmin = await hre.artifacts.readArtifact( 18 | "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol:ProxyAdmin", 19 | ); 20 | 21 | await catchUnknownSigner( 22 | deploy("ResilientOracle", { 23 | from: deployer, 24 | log: true, 25 | deterministicDeployment: false, 26 | args: [vBNBAddress, VAIAddress, boundValidator.address], 27 | proxy: { 28 | owner: proxyOwnerAddress, 29 | proxyContract: "OptimizedTransparentUpgradeableProxy", 30 | viaAdminContract: { 31 | name: "DefaultProxyAdmin", 32 | artifact: defaultProxyAdmin, 33 | }, 34 | }, 35 | }), 36 | ); 37 | }; 38 | 39 | export default func; 40 | func.tags = ["update-resilientOracle"]; 41 | func.skip = async env => !env.network.live; 42 | -------------------------------------------------------------------------------- /deploy/5-dependencies-bnb-lst-oracles.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) => { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | 11 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 12 | 13 | await deploy("MockAnkrBNB", { 14 | from: deployer, 15 | log: true, 16 | autoMine: true, 17 | skipIfAlreadyDeployed: true, 18 | args: ["Ankr Staked BNB ", "ankrBNB", "18"], 19 | }); 20 | 21 | const ankrBNBContract = await ethers.getContract("MockAnkrBNB"); 22 | 23 | if ((await ankrBNBContract.owner()) === deployer) { 24 | await ankrBNBContract.transferOwnership(proxyOwnerAddress); 25 | } 26 | 27 | await deploy("MockWBETH", { 28 | from: deployer, 29 | log: true, 30 | autoMine: true, // speed up deployment on local network (ganache, hardhat), no effect on live networks 31 | skipIfAlreadyDeployed: true, 32 | args: ["Wrapped Binance Beacon ETH", "wBETH", "18"], 33 | }); 34 | 35 | const wBETHContract = await ethers.getContract("MockWBETH"); 36 | 37 | if ((await wBETHContract.owner()) === deployer) { 38 | await wBETHContract.transferOwnership(proxyOwnerAddress); 39 | } 40 | }; 41 | 42 | export default func; 43 | func.tags = ["bnb_lst"]; 44 | func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "bsctestnet"; 45 | -------------------------------------------------------------------------------- /deploy/6-deploy-wstETH-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES, addr0000, assets } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async ({ 8 | getNamedAccounts, 9 | deployments, 10 | network, 11 | artifacts, 12 | }: HardhatRuntimeEnvironment) => { 13 | const { deploy } = deployments; 14 | const { deployer } = await getNamedAccounts(); 15 | 16 | console.log(`Deployer ${deployer}`); 17 | 18 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 19 | 20 | const { stETHAddress, wstETHAddress } = ADDRESSES[network.name]; 21 | const WETHAsset = assets[network.name].find(asset => asset.token === "WETH"); 22 | const WETHAddress = WETHAsset?.address ?? addr0000; 23 | 24 | const defaultProxyAdmin = await artifacts.readArtifact( 25 | "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol:ProxyAdmin", 26 | ); 27 | 28 | const oracle = await ethers.getContract("ResilientOracle"); 29 | 30 | // Equivalence and NonEquivalence is related to if the oracle will 31 | // assume 1/1 price ration between stETH/ETH or 32 | // will get stETH/USD price from secondary market 33 | 34 | await deploy("WstETHOracle_Equivalence", { 35 | contract: "WstETHOracle", 36 | from: deployer, 37 | log: true, 38 | deterministicDeployment: false, 39 | args: [wstETHAddress, WETHAddress, stETHAddress, oracle.address, true], 40 | proxy: { 41 | owner: proxyOwnerAddress, 42 | proxyContract: "OptimizedTransparentUpgradeableProxy", 43 | viaAdminContract: { 44 | name: "DefaultProxyAdmin", 45 | artifact: defaultProxyAdmin, 46 | }, 47 | }, 48 | }); 49 | 50 | await deploy("WstETHOracle_NonEquivalence", { 51 | contract: "WstETHOracle", 52 | from: deployer, 53 | log: true, 54 | deterministicDeployment: false, 55 | args: [wstETHAddress, WETHAddress, stETHAddress, oracle.address, false], 56 | proxy: { 57 | owner: proxyOwnerAddress, 58 | proxyContract: "OptimizedTransparentUpgradeableProxy", 59 | viaAdminContract: { 60 | name: "DefaultProxyAdmin", 61 | artifact: defaultProxyAdmin, 62 | }, 63 | }, 64 | }); 65 | }; 66 | 67 | export default func; 68 | func.tags = ["wsteth"]; 69 | func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "ethereum" && hre.network.name !== "sepolia"; 70 | -------------------------------------------------------------------------------- /deploy/7-dependencies-pendle-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) => { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | 11 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 12 | 13 | await deploy("MockPendlePtOracle", { 14 | contract: "MockPendlePtOracle", 15 | from: deployer, 16 | log: true, 17 | autoMine: true, // speed up deployment on local network (ganache, hardhat), no effect on live networks 18 | skipIfAlreadyDeployed: true, 19 | args: [], 20 | }); 21 | 22 | const pendleOracleContract = await ethers.getContract("MockPendlePtOracle"); 23 | 24 | if ((await pendleOracleContract.owner()) === deployer) { 25 | await pendleOracleContract.transferOwnership(proxyOwnerAddress); 26 | } 27 | }; 28 | 29 | export default func; 30 | func.tags = ["pendle", "mock-pt-oracle"]; 31 | func.skip = async (hre: HardhatRuntimeEnvironment) => 32 | hre.network.name !== "sepolia" && hre.network.name !== "bsctestnet"; 33 | -------------------------------------------------------------------------------- /deploy/8-dependencies-weETH-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) => { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | 11 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 12 | 13 | await deploy("MockEtherFiLiquidityPool", { 14 | from: deployer, 15 | contract: "MockEtherFiLiquidityPool", 16 | args: [], 17 | log: true, 18 | autoMine: true, 19 | skipIfAlreadyDeployed: true, 20 | }); 21 | 22 | const mockEtherFiLiquidityPool = await ethers.getContract("MockEtherFiLiquidityPool"); 23 | await mockEtherFiLiquidityPool.transferOwnership(proxyOwnerAddress); 24 | }; 25 | 26 | export default func; 27 | func.tags = ["weETH"]; 28 | func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "sepolia"; 29 | -------------------------------------------------------------------------------- /deploy/8-deploy-weETH-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async ({ 8 | getNamedAccounts, 9 | deployments, 10 | network, 11 | artifacts, 12 | }: HardhatRuntimeEnvironment) => { 13 | const { deploy } = deployments; 14 | const { deployer } = await getNamedAccounts(); 15 | 16 | const resilientOracle = await ethers.getContract("ResilientOracle"); 17 | const chainlinkOracle = await ethers.getContract("ChainlinkOracle"); 18 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 19 | const defaultProxyAdmin = await artifacts.readArtifact( 20 | "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol:ProxyAdmin", 21 | ); 22 | let { EtherFiLiquidityPool } = ADDRESSES[network.name]; 23 | const { weETH, eETH, WETH } = ADDRESSES[network.name]; 24 | 25 | EtherFiLiquidityPool = EtherFiLiquidityPool || (await ethers.getContract("MockEtherFiLiquidityPool")).address; 26 | 27 | if (network.name === "sepolia") { 28 | await deploy("WeETHOracle", { 29 | from: deployer, 30 | log: true, 31 | deterministicDeployment: false, 32 | args: [EtherFiLiquidityPool, weETH, eETH, resilientOracle.address], 33 | proxy: { 34 | owner: proxyOwnerAddress, 35 | proxyContract: "OptimizedTransparentUpgradeableProxy", 36 | viaAdminContract: { 37 | name: "DefaultProxyAdmin", 38 | artifact: defaultProxyAdmin, 39 | }, 40 | }, 41 | skipIfAlreadyDeployed: true, 42 | }); 43 | } else { 44 | await deploy("WeETHOracle_Equivalence", { 45 | contract: "WeETHOracle", 46 | from: deployer, 47 | log: true, 48 | deterministicDeployment: false, 49 | args: [EtherFiLiquidityPool, weETH, WETH, resilientOracle.address], 50 | proxy: { 51 | owner: proxyOwnerAddress, 52 | proxyContract: "OptimizedTransparentUpgradeableProxy", 53 | viaAdminContract: { 54 | name: "DefaultProxyAdmin", 55 | artifact: defaultProxyAdmin, 56 | }, 57 | }, 58 | skipIfAlreadyDeployed: true, 59 | }); 60 | 61 | await deploy("WeETHOracle_NonEquivalence", { 62 | contract: "OneJumpOracle", 63 | from: deployer, 64 | log: true, 65 | deterministicDeployment: false, 66 | args: [weETH, WETH, resilientOracle.address, chainlinkOracle.address], 67 | proxy: { 68 | owner: proxyOwnerAddress, 69 | proxyContract: "OptimizedTransparentUpgradeableProxy", 70 | viaAdminContract: { 71 | name: "DefaultProxyAdmin", 72 | artifact: defaultProxyAdmin, 73 | }, 74 | }, 75 | skipIfAlreadyDeployed: true, 76 | }); 77 | } 78 | }; 79 | 80 | export default func; 81 | func.tags = ["weETH"]; 82 | func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "ethereum" && hre.network.name !== "sepolia"; 83 | -------------------------------------------------------------------------------- /deploy/9-dependencies-sfrax-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) => { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | 11 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 12 | 13 | await deploy("MockSFrax", { 14 | contract: "MockSFrax", 15 | from: deployer, 16 | log: true, 17 | autoMine: true, // speed up deployment on local network (ganache, hardhat), no effect on live networks 18 | skipIfAlreadyDeployed: true, 19 | args: ["Staked FRAX", "sFRAX", 18], 20 | }); 21 | 22 | const mockSFraxContract = await ethers.getContract("MockSFrax"); 23 | 24 | if ((await mockSFraxContract.owner()) === deployer) { 25 | await mockSFraxContract.transferOwnership(proxyOwnerAddress); 26 | } 27 | }; 28 | 29 | export default func; 30 | func.tags = ["sFraxOracle"]; 31 | func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "sepolia"; 32 | -------------------------------------------------------------------------------- /deploy/9-deploy-sfrax-oracle.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { DeployFunction } from "hardhat-deploy/dist/types"; 3 | import { HardhatRuntimeEnvironment } from "hardhat/types"; 4 | 5 | import { ADDRESSES } from "../helpers/deploymentConfig"; 6 | 7 | const func: DeployFunction = async ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) => { 8 | const { deploy } = deployments; 9 | const { deployer } = await getNamedAccounts(); 10 | 11 | const oracle = await ethers.getContract("ResilientOracle"); 12 | const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer; 13 | 14 | const { sFRAX, FRAX } = ADDRESSES[network.name]; 15 | 16 | await deploy("SFraxOracle", { 17 | contract: "SFraxOracle", 18 | from: deployer, 19 | log: true, 20 | deterministicDeployment: false, 21 | args: [sFRAX || (await ethers.getContract("MockSFrax")).address, FRAX, oracle.address], 22 | proxy: { 23 | owner: proxyOwnerAddress, 24 | proxyContract: "OptimizedTransparentProxy", 25 | }, 26 | skipIfAlreadyDeployed: true, 27 | }); 28 | }; 29 | 30 | export default func; 31 | func.tags = ["sFraxOracle"]; 32 | func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "ethereum" && hre.network.name !== "sepolia"; 33 | -------------------------------------------------------------------------------- /deployments/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/deployments/.gitkeep -------------------------------------------------------------------------------- /deployments/arbitrumone/.chainId: -------------------------------------------------------------------------------- 1 | 42161 -------------------------------------------------------------------------------- /deployments/arbitrumone_addresses.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "arbitrumone", 3 | "chainId": "42161", 4 | "addresses": { 5 | "BoundValidator": "0x2245FA2420925Cd3C2D889Ddc5bA1aefEF0E14CF", 6 | "BoundValidator_Implementation": "0xC1F2846D5bcA25178743a0060Fd356b2E0fd51E8", 7 | "BoundValidator_Proxy": "0x2245FA2420925Cd3C2D889Ddc5bA1aefEF0E14CF", 8 | "DefaultProxyAdmin": "0xF6fF3e9459227f0cDE8B102b90bE25960317b216", 9 | "RedStoneOracle": "0xF792C4D3BdeF534D6d1dcC305056D00C95453dD6", 10 | "RedStoneOracle_Implementation": "0xf5a03c36228b73F654d03601B90A37FfcFe1Ad2a", 11 | "RedStoneOracle_Proxy": "0xF792C4D3BdeF534D6d1dcC305056D00C95453dD6", 12 | "ResilientOracle": "0xd55A98150e0F9f5e3F6280FC25617A5C93d96007", 13 | "ResilientOracle_Implementation": "0x3E6bed944d75078EFc03bE8aa935a464Cc49cf0e", 14 | "ResilientOracle_Proxy": "0xd55A98150e0F9f5e3F6280FC25617A5C93d96007", 15 | "SequencerChainlinkOracle": "0x9cd9Fcc7E3dEDA360de7c080590AaD377ac9F113", 16 | "SequencerChainlinkOracle_Implementation": "0x9E52EFCAD3db5191B4Cb69CaBdCe4F356119F8d8", 17 | "SequencerChainlinkOracle_Proxy": "0x9cd9Fcc7E3dEDA360de7c080590AaD377ac9F113", 18 | "weETHOneJumpChainlinkOracle": "0x09eA4825a5e2FB2CB9a44F317c22e7D65053ea9d", 19 | "weETHOneJumpChainlinkOracle_Implementation": "0x73fBdF1cBEeccC8bc11564527f5E8B49A64D95dA", 20 | "weETHOneJumpChainlinkOracle_Proxy": "0x09eA4825a5e2FB2CB9a44F317c22e7D65053ea9d", 21 | "wstETHOneJumpChainlinkOracle": "0x748DeFdbaE5215cdF0C436c538804823b55D76bc", 22 | "wstETHOneJumpChainlinkOracle_Implementation": "0x546149415DA22B6A53CD82254ad0c4cd03671312", 23 | "wstETHOneJumpChainlinkOracle_Proxy": "0x748DeFdbaE5215cdF0C436c538804823b55D76bc" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /deployments/arbitrumsepolia/.chainId: -------------------------------------------------------------------------------- 1 | 421614 -------------------------------------------------------------------------------- /deployments/arbitrumsepolia_addresses.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "arbitrumsepolia", 3 | "chainId": "421614", 4 | "addresses": { 5 | "BoundValidator": "0xfe6bc1545Cc14C131bacA97476D6035ffcC0b889", 6 | "BoundValidator_Implementation": "0x12702e23acf7B110f8B6F8681E817f8A76a39A81", 7 | "BoundValidator_Proxy": "0xfe6bc1545Cc14C131bacA97476D6035ffcC0b889", 8 | "ChainlinkOracle": "0xeDd02c7FfA31490b4107e8f2c25e9198a04F9E45", 9 | "ChainlinkOracle_Implementation": "0xC75b363aEBd490FBb43c4BF5Fe0961Ea3c0A0791", 10 | "ChainlinkOracle_Proxy": "0xeDd02c7FfA31490b4107e8f2c25e9198a04F9E45", 11 | "DefaultProxyAdmin": "0xA78A1Df376c3CEeBC5Fab574fe6EdDbbF76fd03e", 12 | "RedStoneOracle": "0x15058891ca0c71Bd724b873c41596A682420613C", 13 | "RedStoneOracle_Implementation": "0x30DA2116bFc1474FaE803531620AAB34b118D9dE", 14 | "RedStoneOracle_Proxy": "0x15058891ca0c71Bd724b873c41596A682420613C", 15 | "ResilientOracle": "0x6708bAd042916B47311c8078b29d7f432342102F", 16 | "ResilientOracle_Implementation": "0xbeF4F9590Bb7B3a7620b6444Aca5D81471019d8C", 17 | "ResilientOracle_Proxy": "0x6708bAd042916B47311c8078b29d7f432342102F", 18 | "weETHOneJumpChainlinkOracle": "0x4f894aC6F5e2E2bD72632B137E28234339Db3D53", 19 | "weETHOneJumpChainlinkOracle_Implementation": "0xd53226E153a7F525ca2f7481bDf6E284767347dC", 20 | "weETHOneJumpChainlinkOracle_Proxy": "0x4f894aC6F5e2E2bD72632B137E28234339Db3D53", 21 | "wstETHOneJumpChainlinkOracle": "0x06b47B32d9C4D8f948EB3FFDB4a1ecE93794f922", 22 | "wstETHOneJumpChainlinkOracle_Implementation": "0x01f8d4A0178ceB60B2fFBf8736765198c7392607", 23 | "wstETHOneJumpChainlinkOracle_Proxy": "0x06b47B32d9C4D8f948EB3FFDB4a1ecE93794f922" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /deployments/basemainnet/.chainId: -------------------------------------------------------------------------------- 1 | 8453 -------------------------------------------------------------------------------- /deployments/basemainnet_addresses.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "basemainnet", 3 | "chainId": "8453", 4 | "addresses": { 5 | "BoundValidator": "0x66dDE062D3DC1BB5223A0096EbB89395d1f11DB0", 6 | "BoundValidator_Implementation": "0xa96BCD4F158CBD005e5b38C3e5cF2094BaE6159A", 7 | "BoundValidator_Proxy": "0x66dDE062D3DC1BB5223A0096EbB89395d1f11DB0", 8 | "ChainlinkOracle": "0x6F2eA73597955DB37d7C06e1319F0dC7C7455dEb", 9 | "ChainlinkOracle_Implementation": "0x0C7fc60FA92A76739f13Ce9A870aA4DF92350353", 10 | "ChainlinkOracle_Proxy": "0x6F2eA73597955DB37d7C06e1319F0dC7C7455dEb", 11 | "DefaultProxyAdmin": "0x7B06EF6b68648C61aFE0f715740fE3950B90746B", 12 | "RedStoneOracle": "0xd101Bf51937A6718F402dA944CbfdcD12bB6a6eb", 13 | "RedStoneOracle_Implementation": "0xaA4E642752DFba323a912Db2e1D7F0AD1052637e", 14 | "RedStoneOracle_Proxy": "0xd101Bf51937A6718F402dA944CbfdcD12bB6a6eb", 15 | "ResilientOracle": "0xcBBf58bD5bAdE357b634419B70b215D5E9d6FbeD", 16 | "ResilientOracle_Implementation": "0xb87c9c8fB47B10960c43EBbaf37F4a2e222ec9E3", 17 | "ResilientOracle_Proxy": "0xcBBf58bD5bAdE357b634419B70b215D5E9d6FbeD", 18 | "wstETHOneJumpChainlinkOracle": "0x007e6Bd6993892b39210a7116506D6eA417B7565", 19 | "wstETHOneJumpChainlinkOracle_Implementation": "0x285a2577030ce7a791c36a58b278DAA94b982041", 20 | "wstETHOneJumpChainlinkOracle_Proxy": "0x007e6Bd6993892b39210a7116506D6eA417B7565", 21 | "wsuperOETHb_ERC4626Oracle": "0x2ad7dFf3380A0b75dC0bB1f3B38C105AB5B6D818" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /deployments/basesepolia/.chainId: -------------------------------------------------------------------------------- 1 | 84532 -------------------------------------------------------------------------------- /deployments/basesepolia_addresses.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "basesepolia", 3 | "chainId": "84532", 4 | "addresses": { 5 | "BoundValidator": "0xC76284488E57554A457A75a8b166fB2ADAB430dB", 6 | "BoundValidator_Implementation": "0x9D6aF23E1E42e1eB341eE81cC91855E1f94aDBA0", 7 | "BoundValidator_Proxy": "0xC76284488E57554A457A75a8b166fB2ADAB430dB", 8 | "ChainlinkOracle": "0x801aB33A69AD867500fbCda7b3dB66C73151494b", 9 | "ChainlinkOracle_Implementation": "0x8b5d2A92AF7197f2Ba4aBf524886650038990163", 10 | "ChainlinkOracle_Proxy": "0x801aB33A69AD867500fbCda7b3dB66C73151494b", 11 | "DefaultProxyAdmin": "0xB85dD19112c4BF1240FeD0f26E8D0b0576a82546", 12 | "RedStoneOracle": "0x8267FE3f75E0A37ee34e113E767F9C9727206838", 13 | "RedStoneOracle_Implementation": "0x8585Fafc1169da0AEe141B2cEBaBEb2d1709cC5b", 14 | "RedStoneOracle_Proxy": "0x8267FE3f75E0A37ee34e113E767F9C9727206838", 15 | "ResilientOracle": "0xC34871C982cf0Bc6e7aCa2c2670Bc319bDA1C744", 16 | "ResilientOracle_Implementation": "0x398f2A7E04c38f57E5282Dd612c45e1d924A0590", 17 | "ResilientOracle_Proxy": "0xC34871C982cf0Bc6e7aCa2c2670Bc319bDA1C744", 18 | "wstETHOneJumpChainlinkOracle": "0x71e7AAcb01C5764A56DB92aa31aA473e839d964F", 19 | "wstETHOneJumpChainlinkOracle_Implementation": "0xCE305b594A7714E9ed8eDE23c111aFf6A2d54E0e", 20 | "wstETHOneJumpChainlinkOracle_Proxy": "0x71e7AAcb01C5764A56DB92aa31aA473e839d964F", 21 | "wsuperOETHb_ERC4626Oracle": "0x72050243b23a7f0f74D37e1B85Df9D6486D1a331" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /deployments/berachainbepolia/.chainId: -------------------------------------------------------------------------------- 1 | 80069 -------------------------------------------------------------------------------- /deployments/berachainbepolia_addresses.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "berachainbepolia", 3 | "chainId": "80069", 4 | "addresses": { 5 | "BoundValidator": "0xd3A635930300ea87548A1C3428Ac5DDfE3FFE66E", 6 | "BoundValidator_Implementation": "0xd24c0795BaEA6D79a45def90889bc4Dd4fd19a62", 7 | "BoundValidator_Proxy": "0xd3A635930300ea87548A1C3428Ac5DDfE3FFE66E", 8 | "ChainlinkOracle": "0xF7451caCcb32E6E3695e4B4bcF42152D57B73aD5", 9 | "ChainlinkOracle_Implementation": "0x9eA68754e5AB4717b2b0Dd310f7fA03A9c57c0Df", 10 | "ChainlinkOracle_Proxy": "0xF7451caCcb32E6E3695e4B4bcF42152D57B73aD5", 11 | "DefaultProxyAdmin": "0x09f0Cf4eD50ed01994900CE9ee1ae85BFECd5c66", 12 | "RedStoneOracle": "0xedc00668FC314fcc85a574c8DBa0BB205810F247", 13 | "RedStoneOracle_Implementation": "0x33baAA71Fdb915275908c80A383874096c5ecdEa", 14 | "RedStoneOracle_Proxy": "0xedc00668FC314fcc85a574c8DBa0BB205810F247", 15 | "ResilientOracle": "0x150B667d42FB80409f162aB84065f0c8E9B3A7a0", 16 | "ResilientOracle_Implementation": "0xffCb974c4E2c9EE9107d966530d485bDBd98bBAA", 17 | "ResilientOracle_Proxy": "0x150B667d42FB80409f162aB84065f0c8E9B3A7a0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /deployments/bscmainnet/.chainId: -------------------------------------------------------------------------------- 1 | 56 -------------------------------------------------------------------------------- /deployments/bsctestnet/.chainId: -------------------------------------------------------------------------------- 1 | 97 -------------------------------------------------------------------------------- /deployments/ethereum/.chainId: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /deployments/opbnbmainnet/.chainId: -------------------------------------------------------------------------------- 1 | 204 -------------------------------------------------------------------------------- /deployments/opbnbmainnet_addresses.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "opbnbmainnet", 3 | "chainId": "204", 4 | "addresses": { 5 | "BinanceOracle": "0xB09EC9B628d04E1287216Aa3e2432291f50F9588", 6 | "BinanceOracle_Implementation": "0x7B9BFF3AEbAcE3715660e6340370810f10481b53", 7 | "BinanceOracle_Proxy": "0xB09EC9B628d04E1287216Aa3e2432291f50F9588", 8 | "BoundValidator": "0xd1f80C371C6E2Fa395A5574DB3E3b4dAf43dadCE", 9 | "BoundValidator_Implementation": "0x47C33167d13eD2374161A6f0A9b55fc4cad09897", 10 | "BoundValidator_Proxy": "0xd1f80C371C6E2Fa395A5574DB3E3b4dAf43dadCE", 11 | "DefaultProxyAdmin": "0xF77bD1D893F67b3EB2Cd256239c98Ba3F238fb52", 12 | "ResilientOracle": "0x8f3618c4F0183e14A218782c116fb2438571dAC9", 13 | "ResilientOracle_Implementation": "0xbC3ee948Ba5D78880c6ECb005274257e60d017c8", 14 | "ResilientOracle_Proxy": "0x8f3618c4F0183e14A218782c116fb2438571dAC9" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /deployments/opbnbtestnet/.chainId: -------------------------------------------------------------------------------- 1 | 5611 -------------------------------------------------------------------------------- /deployments/opbnbtestnet_addresses.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "opbnbtestnet", 3 | "chainId": "5611", 4 | "addresses": { 5 | "BinanceOracle": "0x496B6b03469472572C47bdB407d5549b244a74F2", 6 | "BinanceOracle_Implementation": "0x74E708A7F5486ed73CCCAe54B63e71B1988F1383", 7 | "BinanceOracle_Proxy": "0x496B6b03469472572C47bdB407d5549b244a74F2", 8 | "BoundValidator": "0x049537Bb065e6253e9D8D08B45Bf6b753657A746", 9 | "BoundValidator_Implementation": "0x95d1C5f11C7d84fb60bf0cd4dfCCdDE664cb0Af0", 10 | "BoundValidator_Proxy": "0x049537Bb065e6253e9D8D08B45Bf6b753657A746", 11 | "DefaultProxyAdmin": "0xB1281ADC816fba7df64B798D7A0BC4bd2a6d42f4", 12 | "ResilientOracle": "0xEF4e53a9A4565ef243A2f0ee9a7fc2410E1aA623", 13 | "ResilientOracle_Implementation": "0xa37791D28C282b997Eed9e5dAbc8961691e83D5B", 14 | "ResilientOracle_Proxy": "0xEF4e53a9A4565ef243A2f0ee9a7fc2410E1aA623" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /deployments/opmainnet/.chainId: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /deployments/opmainnet_addresses.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "opmainnet", 3 | "chainId": "10", 4 | "addresses": { 5 | "BoundValidator": "0x37A04a1eF784448377a19F2b1b67cD40c09eA505", 6 | "BoundValidator_Implementation": "0xF2E4b4D1E5950DEFb09dA18b0B11b81Ebb14cAfA", 7 | "BoundValidator_Proxy": "0x37A04a1eF784448377a19F2b1b67cD40c09eA505", 8 | "DefaultProxyAdmin": "0xeaF9490cBEA6fF9bA1D23671C39a799CeD0DCED2", 9 | "RedStoneOracle": "0x7478e4656F6CCDCa147B6A7314fF68d0C144751a", 10 | "RedStoneOracle_Implementation": "0x8Ab4553f1A705ADc54b52c0a7d2e5BDe4C60e965", 11 | "RedStoneOracle_Proxy": "0x7478e4656F6CCDCa147B6A7314fF68d0C144751a", 12 | "ResilientOracle": "0x21FC48569bd3a6623281f55FC1F8B48B9386907b", 13 | "ResilientOracle_Implementation": "0xc5e9fD641327201B648a1c3aE2e32c837fA103Db", 14 | "ResilientOracle_Proxy": "0x21FC48569bd3a6623281f55FC1F8B48B9386907b", 15 | "SequencerChainlinkOracle": "0x1076e5A60F1aC98e6f361813138275F1179BEb52", 16 | "SequencerChainlinkOracle_Implementation": "0xe57AfB8198008a487F95bDDE5F078ca81682f474", 17 | "SequencerChainlinkOracle_Proxy": "0x1076e5A60F1aC98e6f361813138275F1179BEb52" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /deployments/opsepolia/.chainId: -------------------------------------------------------------------------------- 1 | 11155420 -------------------------------------------------------------------------------- /deployments/opsepolia_addresses.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "opsepolia", 3 | "chainId": "11155420", 4 | "addresses": { 5 | "BoundValidator": "0x482469F1DA6Ec736cacF6361Ec41621f811A6800", 6 | "BoundValidator_Implementation": "0x64f3Faa5F36E9d55cD0AAD7F23B000D5bc93F6d4", 7 | "BoundValidator_Proxy": "0x482469F1DA6Ec736cacF6361Ec41621f811A6800", 8 | "ChainlinkOracle": "0x493C3f543AEa37EefF17D823f27Cb1feAB9f3143", 9 | "ChainlinkOracle_Implementation": "0xE0157e8702aaAcB01A06BBEB81B76A35a9f74E5f", 10 | "ChainlinkOracle_Proxy": "0x493C3f543AEa37EefF17D823f27Cb1feAB9f3143", 11 | "DefaultProxyAdmin": "0xa9aaf2A1cCf2C3a87997942abaA740887cC89241", 12 | "ResilientOracle": "0x6c01ECa2B5C97F135406a3A5531445A7d977D28e", 13 | "ResilientOracle_Implementation": "0x21f8755443d21Fdf2D2FD617C83d0fD317B191A2", 14 | "ResilientOracle_Proxy": "0x6c01ECa2B5C97F135406a3A5531445A7d977D28e" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /deployments/sepolia/.chainId: -------------------------------------------------------------------------------- 1 | 11155111 -------------------------------------------------------------------------------- /deployments/unichainmainnet/.chainId: -------------------------------------------------------------------------------- 1 | 130 -------------------------------------------------------------------------------- /deployments/unichainmainnet_addresses.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unichainmainnet", 3 | "chainId": "130", 4 | "addresses": { 5 | "BoundValidator": "0xfdaA5dEEA7850997dA8A6E2F2Ab42E60F1011C19", 6 | "BoundValidator_Implementation": "0x537EAa6Fc1828641Dd64394709FBA3b1f53EC8ed", 7 | "BoundValidator_Proxy": "0xfdaA5dEEA7850997dA8A6E2F2Ab42E60F1011C19", 8 | "DefaultProxyAdmin": "0x78e9fff2ab8daAB8559070d897C399E5e1C5074c", 9 | "RedStoneOracle": "0x4d41a36D04D97785bcEA57b057C412b278e6Edcc", 10 | "RedStoneOracle_Implementation": "0x2dE4739a9C68B02B54C0d8323752551d724b3cc2", 11 | "RedStoneOracle_Proxy": "0x4d41a36D04D97785bcEA57b057C412b278e6Edcc", 12 | "ResilientOracle": "0x86D04d6FE928D888076851122dc6739551818f7E", 13 | "ResilientOracle_Implementation": "0x30FA1436071fb25Ee5bf32f17DA23f02ee989d4E", 14 | "ResilientOracle_Proxy": "0x86D04d6FE928D888076851122dc6739551818f7E" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /deployments/unichainsepolia/.chainId: -------------------------------------------------------------------------------- 1 | 1301 -------------------------------------------------------------------------------- /deployments/unichainsepolia_addresses.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unichainsepolia", 3 | "chainId": "1301", 4 | "addresses": { 5 | "BoundValidator": "0x51C9F57Ffc0A4dD6d135aa3b856571F5A4e4C6CB", 6 | "BoundValidator_Implementation": "0xA382F5CD9ECf7187C986c170D939A6fA05aF0996", 7 | "BoundValidator_Proxy": "0x51C9F57Ffc0A4dD6d135aa3b856571F5A4e4C6CB", 8 | "DefaultProxyAdmin": "0x256735eFdfDf135bD6991854e0065909e57804aa", 9 | "RedStoneOracle": "0x8683D6902A669Ac479cfcCf2542724a133D4d872", 10 | "RedStoneOracle_Implementation": "0xb180a21eE8372a40636B2990fC0396e03c034aAA", 11 | "RedStoneOracle_Proxy": "0x8683D6902A669Ac479cfcCf2542724a133D4d872", 12 | "ResilientOracle": "0xA469E718BDE2C9939bD29529A38184e97dF0A741", 13 | "ResilientOracle_Implementation": "0x5A4F8Bb10De121EACcCB36C4deD9792B9D5Ce378", 14 | "ResilientOracle_Proxy": "0xA469E718BDE2C9939bD29529A38184e97dF0A741" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /deployments/zksyncmainnet/.chainId: -------------------------------------------------------------------------------- 1 | 324 -------------------------------------------------------------------------------- /deployments/zksyncmainnet_addresses.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zksyncmainnet", 3 | "chainId": "324", 4 | "addresses": { 5 | "BoundValidator": "0x51519cdCDDD05E2ADCFA108f4a960755D9d6ea8b", 6 | "BoundValidator_Implementation": "0x37878481A040E4F6a8856315bdF02Be4a1B4bd6C", 7 | "BoundValidator_Proxy": "0x51519cdCDDD05E2ADCFA108f4a960755D9d6ea8b", 8 | "ChainlinkOracle": "0x4FC29E1d3fFFbDfbf822F09d20A5BE97e59F66E5", 9 | "ChainlinkOracle_Implementation": "0xd55B0bc224288949c3f5D33e0F3A54d8caCc6B35", 10 | "ChainlinkOracle_Proxy": "0x4FC29E1d3fFFbDfbf822F09d20A5BE97e59F66E5", 11 | "DefaultProxyAdmin": "0x8Ea1A989B036f7Ef21bb95CE4E7961522Ca00287", 12 | "RedStoneOracle": "0xFa1e65e714CDfefDC9729130496AB5b5f3708fdA", 13 | "RedStoneOracle_Implementation": "0xD9CC8b33A1F09b84255577044022182229Bf2fc2", 14 | "RedStoneOracle_Proxy": "0xFa1e65e714CDfefDC9729130496AB5b5f3708fdA", 15 | "ResilientOracle": "0xDe564a4C887d5ad315a19a96DC81991c98b12182", 16 | "ResilientOracle_Implementation": "0x88DcFE18AcE5a75659177c9F980C2771D9736e66", 17 | "ResilientOracle_Proxy": "0xDe564a4C887d5ad315a19a96DC81991c98b12182", 18 | "ZkETHOracle": "0x540aA1683E5E5592E0444499bDA41f6DF8de2Dd8", 19 | "ZkETHOracle_Implementation": "0xA62aD5d6e2d9Ea37791824ac3eA0328138f16393", 20 | "ZkETHOracle_Proxy": "0x540aA1683E5E5592E0444499bDA41f6DF8de2Dd8", 21 | "wUSDM_ERC4626Oracle": "0x7Fb95a0B7b933A9F3Fe3Ead4b69B0267BD8Fe55F", 22 | "wstETHOneJumpChainlinkOracle": "0xd2b4352A3C1C452D9D4D11B4F19e28476128798f", 23 | "wstETHOneJumpChainlinkOracle_Implementation": "0xFc8f37ae8f36bB74606fC3E140460be98d1b4d00", 24 | "wstETHOneJumpChainlinkOracle_Proxy": "0xd2b4352A3C1C452D9D4D11B4F19e28476128798f" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /deployments/zksyncsepolia/.chainId: -------------------------------------------------------------------------------- 1 | 300 -------------------------------------------------------------------------------- /deployments/zksyncsepolia_addresses.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zksyncsepolia", 3 | "chainId": "300", 4 | "addresses": { 5 | "BoundValidator": "0x0A4daBeF41C83Af7e30FfC33feC56ba769f3D24b", 6 | "BoundValidator_Implementation": "0xbf34F1Ca52586FDf5AFb7A92712D047B69932c9f", 7 | "BoundValidator_Proxy": "0x0A4daBeF41C83Af7e30FfC33feC56ba769f3D24b", 8 | "ChainlinkOracle": "0x0DFf10dCdb3526010Df01ECc42076C25C27F8323", 9 | "ChainlinkOracle_Implementation": "0x73461E884C256e1B5Ec1FEEF305410C478EA6818", 10 | "ChainlinkOracle_Proxy": "0x0DFf10dCdb3526010Df01ECc42076C25C27F8323", 11 | "DefaultProxyAdmin": "0x18E44f588a4DcF2F7145d35A5C226e129040b6D3", 12 | "RedStoneOracle": "0x3af097f1Dcec172D5ECdD0D1eFA6B118FF15f152", 13 | "RedStoneOracle_Implementation": "0xf66Ee1C402155483d3d1cb05D5294c59916fF3c5", 14 | "RedStoneOracle_Proxy": "0x3af097f1Dcec172D5ECdD0D1eFA6B118FF15f152", 15 | "ResilientOracle": "0x748853B3bE26c46b4562Fd314dfb82708F395bDf", 16 | "ResilientOracle_Implementation": "0x32810ABAE45A08e0BadEF94b753306E8636B39ED", 17 | "ResilientOracle_Proxy": "0x748853B3bE26c46b4562Fd314dfb82708F395bDf", 18 | "ZkETHOracle": "0x6aE071218F81f4e70312d1F435be24AeD70fa53A", 19 | "ZkETHOracle_Implementation": "0x327871D3a9a8Cbeb06a1FD19607Cc11dE5ec74a7", 20 | "ZkETHOracle_Proxy": "0x6aE071218F81f4e70312d1F435be24AeD70fa53A", 21 | "wUSDM_ERC4626Oracle": "0xf1dD9549556F3fae6d8bf4F3283b1D9d2bfb996B", 22 | "wstETHOneJumpChainlinkOracle": "0x832AafFeeD5EC923489744CE37fB35f4F533284e", 23 | "wstETHOneJumpChainlinkOracle_Implementation": "0xE0246761a77090F061C665f89CCAd853d087e9aE", 24 | "wstETHOneJumpChainlinkOracle_Proxy": "0x832AafFeeD5EC923489744CE37fB35f4F533284e" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /docgen-templates/common.hbs: -------------------------------------------------------------------------------- 1 | {{#if (and visible natspec.notice) }} 2 | 3 | {{h}} {{name}} 4 | 5 | {{{natspec.notice}}} 6 | 7 | {{#if signature}} 8 | ```solidity 9 | {{{signature}}} 10 | ``` 11 | {{/if}} 12 | 13 | {{#if natspec.params}} 14 | {{h 2}} Parameters 15 | | Name | Type | Description | 16 | | ---- | ---- | ----------- | 17 | {{#each params}} 18 | | {{name}} | {{type}} | {{{joinLines natspec}}} | 19 | {{/each}} 20 | {{/if}} 21 | 22 | {{#if natspec.returns}} 23 | {{h 2}} Return Values 24 | | Name | Type | Description | 25 | | ---- | ---- | ----------- | 26 | {{#each returns}} 27 | | {{#if name}}{{name}}{{else}}[{{@index}}]{{/if}} | {{type}} | {{{joinLines natspec}}} | 28 | {{/each}} 29 | {{/if}} 30 | 31 | {{#if natspec.custom.event}} 32 | {{h 2}} 📅 Events 33 | {{{ bullet natspec.custom.event }}} 34 | {{/if}} 35 | 36 | {{#if natspec.custom.access}} 37 | {{h 2}} ⛔️ Access Requirements 38 | {{{ bullet natspec.custom.access }}} 39 | {{/if}} 40 | 41 | {{#if natspec.custom.error}} 42 | {{h 2}} ❌ Errors 43 | {{{ bullet natspec.custom.error }}} 44 | {{/if}} 45 | 46 | - - - 47 | 48 | {{/if}} 49 | -------------------------------------------------------------------------------- /docgen-templates/helpers.ts: -------------------------------------------------------------------------------- 1 | export const and = (...args) => args.every(Boolean); 2 | 3 | export const bullet = (docString: string) => 4 | docString 5 | .split("\n") 6 | .map((elem: string) => { 7 | if (elem) { 8 | return `* ${elem}`; 9 | } 10 | return elem; 11 | }) 12 | .join("\n"); 13 | -------------------------------------------------------------------------------- /docgen-templates/page.hbs: -------------------------------------------------------------------------------- 1 | {{h}} {{items.0.natspec.title}} 2 | {{{items.0.natspec.notice}}} 3 | 4 | # Solidity API 5 | 6 | {{#each items}} 7 | {{#hsection}} 8 | {{>item}} 9 | {{/hsection}} 10 | 11 | {{/each}} -------------------------------------------------------------------------------- /docgen-templates/properties.ts: -------------------------------------------------------------------------------- 1 | import { DocItemContext } from "solidity-docgen/dist/site"; 2 | 3 | export const visible = ({ 4 | item, 5 | }: DocItemContext & { item: { visibility: "public" | "external" | "private" | "internal" } }): boolean => 6 | item.visibility === "public" || item.visibility === "external"; 7 | -------------------------------------------------------------------------------- /docs/CONTRIBUTING.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/docs/CONTRIBUTING.md -------------------------------------------------------------------------------- /funding.json: -------------------------------------------------------------------------------- 1 | { 2 | "opRetro": { 3 | "projectId": "0x954e5341d720cd21df77d54d895d113b9ccc06269180e8ea51daeabfa67fc370" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /helpers/deploymentUtils.ts: -------------------------------------------------------------------------------- 1 | import { HardhatRuntimeEnvironment, Network } from "hardhat/types"; 2 | 3 | export const skipAllExcept = (networks: string[]) => async (hre: HardhatRuntimeEnvironment) => 4 | !networks.includes(hre.network.name); 5 | 6 | export const isMainnet = (network: Network) => network.live && !network.tags.testnet; 7 | 8 | export const isTestnet = (network: Network) => network.live && network.tags.testnet; 9 | -------------------------------------------------------------------------------- /marketing-assets/oracles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VenusProtocol/oracle/3cf07f50dc5d2631e0fe2d7fabc7579b0ae7cd35/marketing-assets/oracles.png -------------------------------------------------------------------------------- /networks/mainnet.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /patches/@defi-wonderland+smock+2.4.0.patch: -------------------------------------------------------------------------------- 1 | diff --git a/node_modules/@defi-wonderland/smock/dist/src/utils/hardhat.js b/node_modules/@defi-wonderland/smock/dist/src/utils/hardhat.js 2 | index 15b140c..7a0c157 100644 3 | --- a/node_modules/@defi-wonderland/smock/dist/src/utils/hardhat.js 4 | +++ b/node_modules/@defi-wonderland/smock/dist/src/utils/hardhat.js 5 | @@ -6,7 +6,12 @@ const getHardhatBaseProvider = async (runtime) => { 6 | const maxLoopIterations = 1024; 7 | let currentLoopIterations = 0; 8 | let provider = runtime.network.provider; 9 | - await provider.init(); 10 | + if ('init' in provider) { 11 | + // Newer versions of Hardhat initialize the provider lazily, so we need to 12 | + // call provider.init() explicitly. This is a no-op if the provider is 13 | + // already initialized. 14 | + await provider.init(); 15 | + } 16 | while (provider._wrapped !== undefined) { 17 | provider = provider._wrapped; 18 | currentLoopIterations += 1; 19 | -------------------------------------------------------------------------------- /test/AnkrBNBOracle.ts: -------------------------------------------------------------------------------- 1 | import { smock } from "@defi-wonderland/smock"; 2 | import chai from "chai"; 3 | import { parseUnits } from "ethers/lib/utils"; 4 | import { ethers } from "hardhat"; 5 | 6 | import { IAnkrBNB, ResilientOracleInterface } from "../typechain-types"; 7 | import { addr0000 } from "./utils/data"; 8 | 9 | const { expect } = chai; 10 | chai.use(smock.matchers); 11 | 12 | const BNB_AMOUNT_FOR_ONE_ANKRBNB = parseUnits("1.075370795716558975", 18); 13 | const ANKRBNB_USD_PRICE_DENOMINATOR = parseUnits("1", 18); 14 | const BNB_USD_PRICE = parseUnits("300", 18); // 300 USD for 1 BNB 15 | 16 | describe("AnkrBNBOracle unit tests", () => { 17 | let ankrBNBMock; 18 | let resilientOracleMock; 19 | let ankrBNBOracle; 20 | let ankrBNBOracleFactory; 21 | before(async () => { 22 | // To initialize the provider we need to hit the node with any request 23 | await ethers.getSigners(); 24 | resilientOracleMock = await smock.fake("ResilientOracleInterface"); 25 | resilientOracleMock.getPrice.returns(BNB_USD_PRICE); 26 | 27 | ankrBNBMock = await smock.fake("IAnkrBNB"); 28 | ankrBNBMock.sharesToBonds.returns(BNB_AMOUNT_FOR_ONE_ANKRBNB); 29 | ankrBNBMock.decimals.returns(18); 30 | 31 | ankrBNBOracleFactory = await ethers.getContractFactory("AnkrBNBOracle"); 32 | }); 33 | 34 | describe("deployment", () => { 35 | it("revert if ankrBNB address is 0", async () => { 36 | await expect(ankrBNBOracleFactory.deploy(addr0000, resilientOracleMock.address)).to.be.reverted; 37 | }); 38 | it("revert if ResilientOracle address is 0", async () => { 39 | await expect(ankrBNBOracleFactory.deploy(ankrBNBMock.address, addr0000)).to.be.reverted; 40 | }); 41 | it("should deploy contract", async () => { 42 | ankrBNBOracle = await ankrBNBOracleFactory.deploy(ankrBNBMock.address, resilientOracleMock.address); 43 | }); 44 | }); 45 | 46 | describe("getPrice", () => { 47 | it("revert if ankrBNB address is wrong", async () => { 48 | await expect(ankrBNBOracle.getPrice(addr0000)).to.be.revertedWithCustomError( 49 | ankrBNBOracle, 50 | "InvalidTokenAddress", 51 | ); 52 | }); 53 | 54 | it("should get correct price", async () => { 55 | const expectedPrice = BNB_USD_PRICE.mul(BNB_AMOUNT_FOR_ONE_ANKRBNB).div(ANKRBNB_USD_PRICE_DENOMINATOR); 56 | expect(await ankrBNBOracle.getPrice(ankrBNBMock.address)).to.equal(expectedPrice); 57 | }); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /test/BNBxOracle.ts: -------------------------------------------------------------------------------- 1 | import { smock } from "@defi-wonderland/smock"; 2 | import chai from "chai"; 3 | import { parseUnits } from "ethers/lib/utils"; 4 | import { ethers } from "hardhat"; 5 | 6 | import { ADDRESSES } from "../helpers/deploymentConfig"; 7 | import { BEP20Harness, IStaderStakeManager, ResilientOracleInterface } from "../typechain-types"; 8 | import { addr0000 } from "./utils/data"; 9 | 10 | const { expect } = chai; 11 | chai.use(smock.matchers); 12 | 13 | const { BNBx } = ADDRESSES.bscmainnet; 14 | const EXP_SCALE = parseUnits("1", 18); 15 | const BNB_USD_PRICE = parseUnits("300", 18); // 300 USD for 1 BNB 16 | const BNB_FOR_ONE_BNBX = parseUnits("1.082798704659082054", 18); 17 | 18 | describe("BNBxOracle unit tests", () => { 19 | let BNBxStakeManagerMock; 20 | let resilientOracleMock; 21 | let BNBxOracle; 22 | let BNBxOracleFactory; 23 | let bnbxMock; 24 | before(async () => { 25 | // To initialize the provider we need to hit the node with any request 26 | await ethers.getSigners(); 27 | resilientOracleMock = await smock.fake("ResilientOracleInterface"); 28 | resilientOracleMock.getPrice.returns(BNB_USD_PRICE); 29 | 30 | bnbxMock = await smock.fake("BEP20Harness", { address: BNBx }); 31 | bnbxMock.decimals.returns(18); 32 | 33 | BNBxStakeManagerMock = await smock.fake("IStaderStakeManager"); 34 | BNBxStakeManagerMock.convertBnbXToBnb.returns(BNB_FOR_ONE_BNBX); 35 | BNBxOracleFactory = await ethers.getContractFactory("BNBxOracle"); 36 | }); 37 | 38 | describe("deployment", () => { 39 | it("revert if stakeManager address is 0", async () => { 40 | await expect(BNBxOracleFactory.deploy(addr0000, BNBx, resilientOracleMock.address)).to.be.reverted; 41 | }); 42 | it("revert if BNBx address is 0", async () => { 43 | await expect(BNBxOracleFactory.deploy(BNBxStakeManagerMock.address, addr0000, resilientOracleMock.address)).to.be 44 | .reverted; 45 | }); 46 | it("revert if resilientOracle address is 0", async () => { 47 | await expect(BNBxOracleFactory.deploy(BNBxStakeManagerMock.address, BNBx, addr0000)).to.be.reverted; 48 | }); 49 | it("should deploy contract", async () => { 50 | BNBxOracle = await BNBxOracleFactory.deploy(BNBxStakeManagerMock.address, BNBx, resilientOracleMock.address); 51 | }); 52 | }); 53 | 54 | describe("getPrice", () => { 55 | it("revert if BNBx address is wrong", async () => { 56 | await expect(BNBxOracle.getPrice(addr0000)).to.be.revertedWithCustomError(BNBxOracle, "InvalidTokenAddress"); 57 | }); 58 | 59 | it("should get correct price", async () => { 60 | const expectedPrice = BNB_FOR_ONE_BNBX.mul(BNB_USD_PRICE).div(EXP_SCALE); 61 | expect(await BNBxOracle.getPrice(BNBx)).to.equal(expectedPrice); 62 | }); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /test/ERC4626Oracle.ts: -------------------------------------------------------------------------------- 1 | import { smock } from "@defi-wonderland/smock"; 2 | import chai from "chai"; 3 | import { parseUnits } from "ethers/lib/utils"; 4 | import { ethers } from "hardhat"; 5 | 6 | import { ADDRESSES } from "../helpers/deploymentConfig"; 7 | import { BEP20Harness, IERC4626, ResilientOracleInterface } from "../typechain-types"; 8 | import { addr0000 } from "./utils/data"; 9 | 10 | const { expect } = chai; 11 | chai.use(smock.matchers); 12 | 13 | const { FRAX, sFRAX } = ADDRESSES.ethereum; 14 | const FRAX_USD_PRICE = parseUnits("0.9979", 18); // 0.99 USD for 1 FRAX 15 | 16 | describe("ERC4626Oracle unit tests", () => { 17 | let sFraxMock; 18 | let resilientOracleMock; 19 | let ERC4626OracleFactory; 20 | let ERC4626Oracle; 21 | let fraxMock; 22 | before(async () => { 23 | // To initialize the provider we need to hit the node with any request 24 | await ethers.getSigners(); 25 | resilientOracleMock = await smock.fake("ResilientOracleInterface"); 26 | 27 | sFraxMock = await smock.fake("IERC4626", { address: sFRAX }); 28 | sFraxMock.convertToAssets.returns(parseUnits("1.019194969966192602", 18)); 29 | sFraxMock.decimals.returns(18); 30 | 31 | fraxMock = await smock.fake("BEP20Harness", { address: FRAX }); 32 | fraxMock.decimals.returns(18); 33 | 34 | ERC4626OracleFactory = await ethers.getContractFactory("ERC4626Oracle"); 35 | }); 36 | 37 | describe("deployment", () => { 38 | it("revert if FRAX address is 0", async () => { 39 | await expect(ERC4626OracleFactory.deploy(sFraxMock.address, addr0000, resilientOracleMock.address)).to.be 40 | .reverted; 41 | }); 42 | it("revert if sFRAX address is 0", async () => { 43 | await expect(ERC4626OracleFactory.deploy(addr0000, fraxMock.address, resilientOracleMock.address)).to.be.reverted; 44 | }); 45 | it("should deploy contract", async () => { 46 | ERC4626Oracle = await ERC4626OracleFactory.deploy( 47 | sFraxMock.address, 48 | fraxMock.address, 49 | resilientOracleMock.address, 50 | ); 51 | }); 52 | }); 53 | 54 | describe("getPrice", () => { 55 | it("revert if address is not valid sFrax address", async () => { 56 | await expect(ERC4626Oracle.getPrice(addr0000)).to.be.revertedWithCustomError( 57 | ERC4626Oracle, 58 | "InvalidTokenAddress", 59 | ); 60 | }); 61 | 62 | it("should get correct price of sFrax", async () => { 63 | resilientOracleMock.getPrice.returns(FRAX_USD_PRICE); 64 | const price = await ERC4626Oracle.getPrice(sFraxMock.address); 65 | expect(price).to.equal(parseUnits("1.017054660529263597", 18)); 66 | }); 67 | }); 68 | }); 69 | -------------------------------------------------------------------------------- /test/OneJumpOracle.ts: -------------------------------------------------------------------------------- 1 | import { smock } from "@defi-wonderland/smock"; 2 | import chai from "chai"; 3 | import { parseUnits } from "ethers/lib/utils"; 4 | import { ethers } from "hardhat"; 5 | 6 | import { BEP20Harness, OracleInterface, ResilientOracleInterface } from "../typechain-types"; 7 | import { addr0000 } from "./utils/data"; 8 | 9 | const { expect } = chai; 10 | chai.use(smock.matchers); 11 | 12 | const LDO_ETH_PRICE = parseUnits("0.000945180903526149", 18); // 3.30 USD for 1 LDO 13 | const ETH_USD_PRICE = parseUnits("3496.14", 18); // 3,496.14 USD for 1 ETH 14 | 15 | describe("OneJumpOracle unit tests", () => { 16 | let ldoMock; 17 | let wethMock; 18 | let resilientOracleMock; 19 | let OneJumpOracleFactory; 20 | let OneJumpOracle; 21 | let chainlinkOracleMock; 22 | before(async () => { 23 | // To initialize the provider we need to hit the node with any request 24 | await ethers.getSigners(); 25 | resilientOracleMock = await smock.fake("ResilientOracleInterface"); 26 | chainlinkOracleMock = await smock.fake("OracleInterface"); 27 | 28 | ldoMock = await smock.fake("BEP20Harness"); 29 | ldoMock.decimals.returns(18); 30 | 31 | wethMock = await smock.fake("BEP20Harness"); 32 | wethMock.decimals.returns(18); 33 | 34 | resilientOracleMock.getPrice.whenCalledWith(wethMock.address).returns(ETH_USD_PRICE.toString()); 35 | chainlinkOracleMock.getPrice.whenCalledWith(ldoMock.address).returns(LDO_ETH_PRICE.toString()); 36 | 37 | OneJumpOracleFactory = await ethers.getContractFactory("OneJumpOracle"); 38 | }); 39 | 40 | describe("deployment", () => { 41 | it("revert if correlated token address is 0", async () => { 42 | await expect( 43 | OneJumpOracleFactory.deploy( 44 | addr0000, 45 | wethMock.address, 46 | resilientOracleMock.address, 47 | chainlinkOracleMock.address, 48 | ), 49 | ).to.be.reverted; 50 | }); 51 | 52 | it("revert if underlying token address is 0", async () => { 53 | await expect( 54 | OneJumpOracleFactory.deploy( 55 | ldoMock.address, 56 | addr0000, 57 | resilientOracleMock.address, 58 | chainlinkOracleMock.address, 59 | ), 60 | ).to.be.reverted; 61 | }); 62 | 63 | it("revert if resilient oracle address is 0", async () => { 64 | await expect( 65 | OneJumpOracleFactory.deploy(ldoMock.address, wethMock.address, addr0000, chainlinkOracleMock.address), 66 | ).to.be.reverted; 67 | }); 68 | 69 | it("revert if intermediate oracle address is 0", async () => { 70 | await expect( 71 | OneJumpOracleFactory.deploy(ldoMock.address, wethMock.address, resilientOracleMock.address, addr0000), 72 | ).to.be.reverted; 73 | }); 74 | 75 | it("should deploy contract", async () => { 76 | OneJumpOracle = await OneJumpOracleFactory.deploy( 77 | ldoMock.address, 78 | wethMock.address, 79 | resilientOracleMock.address, 80 | chainlinkOracleMock.address, 81 | ); 82 | }); 83 | }); 84 | 85 | describe("getPrice", () => { 86 | it("revert if address is not valid LDO address", async () => { 87 | await expect(OneJumpOracle.getPrice(addr0000)).to.be.revertedWithCustomError( 88 | OneJumpOracle, 89 | "InvalidTokenAddress", 90 | ); 91 | }); 92 | 93 | it("should get correct price of LDO", async () => { 94 | const price = await OneJumpOracle.getPrice(ldoMock.address); 95 | expect(price).to.equal(parseUnits("3.304484764053910564", 18)); 96 | }); 97 | }); 98 | }); 99 | -------------------------------------------------------------------------------- /test/SFraxOracle.ts: -------------------------------------------------------------------------------- 1 | import { smock } from "@defi-wonderland/smock"; 2 | import chai from "chai"; 3 | import { parseUnits } from "ethers/lib/utils"; 4 | import { ethers } from "hardhat"; 5 | 6 | import { ADDRESSES } from "../helpers/deploymentConfig"; 7 | import { BEP20Harness, ISFrax, ResilientOracleInterface } from "../typechain-types"; 8 | import { addr0000 } from "./utils/data"; 9 | 10 | const { expect } = chai; 11 | chai.use(smock.matchers); 12 | 13 | const { FRAX, sFRAX } = ADDRESSES.ethereum; 14 | const FRAX_USD_PRICE = parseUnits("0.9979", 18); // 0.99 USD for 1 FRAX 15 | 16 | describe("SFraxOracle unit tests", () => { 17 | let sFraxMock; 18 | let resilientOracleMock; 19 | let SFraxOracleFactory; 20 | let SFraxOracle; 21 | let fraxMock; 22 | before(async () => { 23 | // To initialize the provider we need to hit the node with any request 24 | await ethers.getSigners(); 25 | resilientOracleMock = await smock.fake("ResilientOracleInterface"); 26 | 27 | sFraxMock = await smock.fake("ISFrax", { address: sFRAX }); 28 | sFraxMock.convertToAssets.returns(parseUnits("1.019194969966192602", 18)); 29 | sFraxMock.decimals.returns(18); 30 | 31 | fraxMock = await smock.fake("BEP20Harness", { address: FRAX }); 32 | fraxMock.decimals.returns(18); 33 | 34 | SFraxOracleFactory = await ethers.getContractFactory("SFraxOracle"); 35 | }); 36 | 37 | describe("deployment", () => { 38 | it("revert if FRAX address is 0", async () => { 39 | await expect(SFraxOracleFactory.deploy(sFraxMock.address, addr0000, resilientOracleMock.address)).to.be.reverted; 40 | }); 41 | it("revert if sFRAX address is 0", async () => { 42 | await expect(SFraxOracleFactory.deploy(addr0000, fraxMock.address, resilientOracleMock.address)).to.be.reverted; 43 | }); 44 | it("should deploy contract", async () => { 45 | SFraxOracle = await SFraxOracleFactory.deploy(sFraxMock.address, fraxMock.address, resilientOracleMock.address); 46 | }); 47 | }); 48 | 49 | describe("getPrice", () => { 50 | it("revert if address is not valid sFrax address", async () => { 51 | await expect(SFraxOracle.getPrice(addr0000)).to.be.revertedWithCustomError(SFraxOracle, "InvalidTokenAddress"); 52 | }); 53 | 54 | it("should get correct price of sFrax", async () => { 55 | resilientOracleMock.getPrice.returns(FRAX_USD_PRICE); 56 | const price = await SFraxOracle.getPrice(sFraxMock.address); 57 | expect(price).to.equal(parseUnits("1.017054660529263597", 18)); 58 | }); 59 | }); 60 | }); 61 | -------------------------------------------------------------------------------- /test/SlisBNBOracle.ts: -------------------------------------------------------------------------------- 1 | import { smock } from "@defi-wonderland/smock"; 2 | import chai from "chai"; 3 | import { parseUnits } from "ethers/lib/utils"; 4 | import { ethers } from "hardhat"; 5 | 6 | import { ADDRESSES } from "../helpers/deploymentConfig"; 7 | import { BEP20Harness, ISynclubStakeManager, ResilientOracleInterface } from "../typechain-types"; 8 | import { addr0000 } from "./utils/data"; 9 | 10 | const { expect } = chai; 11 | chai.use(smock.matchers); 12 | 13 | const { slisBNB } = ADDRESSES.bscmainnet; 14 | const EXP_SCALE = parseUnits("1", 18); 15 | const BNB_USD_PRICE = parseUnits("300", 18); // 300 USD for 1 BNB 16 | const BNB_FOR_ONE_SLISBNB = parseUnits("1.014061147834812261", 18); 17 | 18 | describe("SlisBNBOracle unit tests", () => { 19 | let SynclubManagerMock; 20 | let resilientOracleMock; 21 | let SlisBNBOracle; 22 | let SlisBNBOracleFactory; 23 | let slisBNBMock; 24 | before(async () => { 25 | // To initialize the provider we need to hit the node with any request 26 | await ethers.getSigners(); 27 | resilientOracleMock = await smock.fake("ResilientOracleInterface"); 28 | resilientOracleMock.getPrice.returns(BNB_USD_PRICE); 29 | 30 | slisBNBMock = await smock.fake("BEP20Harness", { address: slisBNB }); 31 | slisBNBMock.decimals.returns(18); 32 | 33 | SynclubManagerMock = await smock.fake("ISynclubStakeManager"); 34 | SynclubManagerMock.convertSnBnbToBnb.returns(BNB_FOR_ONE_SLISBNB); 35 | SlisBNBOracleFactory = await ethers.getContractFactory("SlisBNBOracle"); 36 | }); 37 | 38 | describe("deployment", () => { 39 | it("revert if SynclubManager address is 0", async () => { 40 | await expect(SlisBNBOracleFactory.deploy(addr0000, slisBNB, resilientOracleMock.address)).to.be.reverted; 41 | }); 42 | it("revert if slisBNB address is 0", async () => { 43 | await expect(SlisBNBOracleFactory.deploy(SynclubManagerMock.address, addr0000, resilientOracleMock.address)).to.be 44 | .reverted; 45 | }); 46 | it("revert if resilientOracle address is 0", async () => { 47 | await expect(SlisBNBOracleFactory.deploy(SynclubManagerMock.address, slisBNB, addr0000)).to.be.reverted; 48 | }); 49 | it("should deploy contract", async () => { 50 | SlisBNBOracle = await SlisBNBOracleFactory.deploy( 51 | SynclubManagerMock.address, 52 | slisBNB, 53 | resilientOracleMock.address, 54 | ); 55 | }); 56 | }); 57 | 58 | describe("getPrice", () => { 59 | it("revert if slisBNB address is wrong", async () => { 60 | await expect(SlisBNBOracle.getPrice(addr0000)).to.be.revertedWithCustomError( 61 | SlisBNBOracle, 62 | "InvalidTokenAddress", 63 | ); 64 | }); 65 | 66 | it("should get correct price", async () => { 67 | const expectedPrice = BNB_FOR_ONE_SLISBNB.mul(BNB_USD_PRICE).div(EXP_SCALE); 68 | expect(await SlisBNBOracle.getPrice(slisBNB)).to.equal(expectedPrice); 69 | }); 70 | }); 71 | }); 72 | -------------------------------------------------------------------------------- /test/StkBNBOracle.ts: -------------------------------------------------------------------------------- 1 | import { smock } from "@defi-wonderland/smock"; 2 | import chai from "chai"; 3 | import { parseUnits } from "ethers/lib/utils"; 4 | import { ethers } from "hardhat"; 5 | 6 | import { ADDRESSES } from "../helpers/deploymentConfig"; 7 | import { BEP20Harness, IPStakePool, ResilientOracleInterface } from "../typechain-types"; 8 | import { addr0000 } from "./utils/data"; 9 | 10 | const { expect } = chai; 11 | chai.use(smock.matchers); 12 | 13 | const { stkBNB } = ADDRESSES.bscmainnet; 14 | const EXP_SCALE = parseUnits("1", 18); 15 | const BNB_USD_PRICE = parseUnits("300", 18); // 300 USD for 1 BNB 16 | const TOTAL_WEI = parseUnits("17173.956674843638040397", 18); 17 | const POOL_TOKEN_SUPPLY = parseUnits("16497.681117925810757967", 18); 18 | 19 | describe("StkBNBOracle unit tests", () => { 20 | let stkBNBStakePoolMock; 21 | let resilientOracleMock; 22 | let StkBNBOracle; 23 | let StkBNBOracleFactory; 24 | let stkBNBMock; 25 | before(async () => { 26 | // To initialize the provider we need to hit the node with any request 27 | await ethers.getSigners(); 28 | resilientOracleMock = await smock.fake("ResilientOracleInterface"); 29 | resilientOracleMock.getPrice.returns(BNB_USD_PRICE); 30 | 31 | stkBNBMock = await smock.fake("BEP20Harness", { address: stkBNB }); 32 | stkBNBMock.decimals.returns(18); 33 | 34 | stkBNBStakePoolMock = await smock.fake("IPStakePool"); 35 | stkBNBStakePoolMock.exchangeRate.returns({ 36 | totalWei: TOTAL_WEI, 37 | poolTokenSupply: POOL_TOKEN_SUPPLY, 38 | }); 39 | StkBNBOracleFactory = await ethers.getContractFactory("StkBNBOracle"); 40 | }); 41 | 42 | describe("deployment", () => { 43 | it("revert if stakePool address is 0", async () => { 44 | await expect(StkBNBOracleFactory.deploy(addr0000, stkBNB, resilientOracleMock.address)).to.be.reverted; 45 | }); 46 | it("revert if stkBNB address is 0", async () => { 47 | await expect(StkBNBOracleFactory.deploy(stkBNBStakePoolMock.address, addr0000, resilientOracleMock.address)).to.be 48 | .reverted; 49 | }); 50 | it("revert if resilientOracle address is 0", async () => { 51 | await expect(StkBNBOracleFactory.deploy(stkBNBStakePoolMock.address, stkBNB, addr0000)).to.be.reverted; 52 | }); 53 | it("should deploy contract", async () => { 54 | StkBNBOracle = await StkBNBOracleFactory.deploy(stkBNBStakePoolMock.address, stkBNB, resilientOracleMock.address); 55 | }); 56 | }); 57 | 58 | describe("getPrice", () => { 59 | it("revert if ankrBNB address is wrong", async () => { 60 | await expect(StkBNBOracle.getPrice(addr0000)).to.be.revertedWithCustomError(StkBNBOracle, "InvalidTokenAddress"); 61 | }); 62 | 63 | it("should get correct price", async () => { 64 | const expectedPrice = TOTAL_WEI.mul(EXP_SCALE).div(POOL_TOKEN_SUPPLY).mul(BNB_USD_PRICE).div(EXP_SCALE); 65 | expect(await StkBNBOracle.getPrice(stkBNB)).to.equal(expectedPrice); 66 | }); 67 | }); 68 | }); 69 | -------------------------------------------------------------------------------- /test/WBETHOracle.ts: -------------------------------------------------------------------------------- 1 | import { smock } from "@defi-wonderland/smock"; 2 | import chai from "chai"; 3 | import { parseUnits } from "ethers/lib/utils"; 4 | import { ethers } from "hardhat"; 5 | 6 | import { assets } from "../helpers/deploymentConfig"; 7 | import { BEP20Harness, IWBETH, ResilientOracleInterface } from "../typechain-types"; 8 | import { addr0000 } from "./utils/data"; 9 | 10 | const { expect } = chai; 11 | chai.use(smock.matchers); 12 | 13 | const WETH = assets.ethereum.find(asset => asset.token === "WETH")?.address; 14 | const EXP_SCALE = parseUnits("1", 18); 15 | const ETH_USD_PRICE = parseUnits("2500", 18); // 2500 USD for 1 ETH 16 | const ETH_FOR_ONE_WBETH = parseUnits("1.030692700354", 18); 17 | 18 | describe("WBETHOracle unit tests", () => { 19 | let wBETH; 20 | let resilientOracleMock; 21 | let WBETHOracle; 22 | let WBETHOracleFactory; 23 | let wethMock; 24 | before(async () => { 25 | // To initialize the provider we need to hit the node with any request 26 | await ethers.getSigners(); 27 | resilientOracleMock = await smock.fake("ResilientOracleInterface"); 28 | resilientOracleMock.getPrice.returns(ETH_USD_PRICE); 29 | 30 | wethMock = await smock.fake("BEP20Harness", { address: WETH }); 31 | wethMock.decimals.returns(18); 32 | 33 | wBETH = await smock.fake("IWBETH"); 34 | wBETH.exchangeRate.returns(ETH_FOR_ONE_WBETH); 35 | wBETH.decimals.returns(18); 36 | WBETHOracleFactory = await ethers.getContractFactory("WBETHOracle"); 37 | }); 38 | 39 | describe("deployment", () => { 40 | it("revert if WBETH address is 0", async () => { 41 | await expect(WBETHOracleFactory.deploy(addr0000, wethMock.address, resilientOracleMock.address)).to.be.reverted; 42 | }); 43 | it("revert if ETH address is 0", async () => { 44 | await expect(WBETHOracleFactory.deploy(wBETH.address, addr0000, resilientOracleMock.address)).to.be.reverted; 45 | }); 46 | it("revert if resilientOracle address is 0", async () => { 47 | await expect(WBETHOracleFactory.deploy(wBETH.address, wethMock.address, addr0000)).to.be.reverted; 48 | }); 49 | it("should deploy contract", async () => { 50 | WBETHOracle = await WBETHOracleFactory.deploy(wBETH.address, wethMock.address, resilientOracleMock.address); 51 | }); 52 | }); 53 | 54 | describe("getPrice", () => { 55 | it("revert if WBETH address is wrong", async () => { 56 | await expect(WBETHOracle.getPrice(addr0000)).to.be.revertedWithCustomError(WBETHOracle, "InvalidTokenAddress"); 57 | }); 58 | 59 | it("should get correct price", async () => { 60 | const expectedPrice = ETH_FOR_ONE_WBETH.mul(ETH_USD_PRICE).div(EXP_SCALE); 61 | expect(await WBETHOracle.getPrice(wBETH.address)).to.equal(expectedPrice); 62 | }); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /test/WeETHOracle.ts: -------------------------------------------------------------------------------- 1 | import { smock } from "@defi-wonderland/smock"; 2 | import chai from "chai"; 3 | import { parseUnits } from "ethers/lib/utils"; 4 | import { ethers } from "hardhat"; 5 | 6 | import { ADDRESSES } from "../helpers/deploymentConfig"; 7 | import { BEP20Harness, ResilientOracleInterface } from "../typechain-types"; 8 | import { addr0000 } from "./utils/data"; 9 | 10 | const { expect } = chai; 11 | chai.use(smock.matchers); 12 | 13 | const { weETH, eETH } = ADDRESSES.ethereum; 14 | const ETH_USD_PRICE = parseUnits("3100", 18); // 3100 USD for 1 ETH 15 | 16 | describe("WeETHOracle unit tests", () => { 17 | let weETHMock; 18 | let resilientOracleMock; 19 | let WeETHOracleFactory; 20 | let WeETHOracle; 21 | let eETHMock; 22 | let mockLiquidityPool; 23 | before(async () => { 24 | // To initialize the provider we need to hit the node with any request 25 | await ethers.getSigners(); 26 | resilientOracleMock = await smock.fake("ResilientOracleInterface"); 27 | resilientOracleMock.getPrice.returns(ETH_USD_PRICE); 28 | 29 | eETHMock = await smock.fake("BEP20Harness", { address: eETH }); 30 | eETHMock.decimals.returns(18); 31 | 32 | weETHMock = await smock.fake("BEP20Harness", { address: weETH }); 33 | weETHMock.decimals.returns(18); 34 | 35 | const MockLiquidityPoolFactory = await ethers.getContractFactory("MockEtherFiLiquidityPool"); 36 | mockLiquidityPool = await MockLiquidityPoolFactory.deploy(); 37 | await mockLiquidityPool.setAmountPerShare(parseUnits("1.032226887617316822", 18)); 38 | 39 | WeETHOracleFactory = await ethers.getContractFactory("WeETHOracle"); 40 | }); 41 | 42 | describe("deployment", () => { 43 | it("revert if liquidity pool address is 0", async () => { 44 | await expect( 45 | WeETHOracleFactory.deploy(addr0000, weETHMock.address, eETHMock.address, resilientOracleMock.address), 46 | ).to.be.reverted; 47 | }); 48 | 49 | it("revert if weETH address is 0", async () => { 50 | await expect( 51 | WeETHOracleFactory.deploy(mockLiquidityPool.address, addr0000, eETHMock.address, resilientOracleMock.address), 52 | ).to.be.reverted; 53 | }); 54 | it("revert if eETH address is 0", async () => { 55 | await expect( 56 | WeETHOracleFactory.deploy(mockLiquidityPool.address, weETHMock.address, addr0000, resilientOracleMock.address), 57 | ).to.be.reverted; 58 | }); 59 | it("revert if resilient oracle address is 0", async () => { 60 | await expect(WeETHOracleFactory.deploy(mockLiquidityPool.address, weETHMock.address, eETHMock.address, addr0000)) 61 | .to.be.reverted; 62 | }); 63 | it("should deploy contract", async () => { 64 | WeETHOracle = await WeETHOracleFactory.deploy( 65 | mockLiquidityPool.address, 66 | weETHMock.address, 67 | eETHMock.address, 68 | resilientOracleMock.address, 69 | ); 70 | }); 71 | }); 72 | 73 | describe("getPrice", () => { 74 | it("revert if address is not valid weETH address", async () => { 75 | await expect(WeETHOracle.getPrice(addr0000)).to.be.revertedWithCustomError(WeETHOracle, "InvalidTokenAddress"); 76 | }); 77 | 78 | it("should get correct price of weETH", async () => { 79 | const price = await WeETHOracle.getPrice(weETHMock.address); 80 | // 1.032226887617316822 (weETH to eETH exchange rate) * 3100 (eETH price) = 3199.9033516136821482 81 | expect(price).to.equal(parseUnits("3199.9033516136821482", 18)); 82 | }); 83 | }); 84 | }); 85 | -------------------------------------------------------------------------------- /test/WstETHOracleV2.ts: -------------------------------------------------------------------------------- 1 | import { smock } from "@defi-wonderland/smock"; 2 | import chai from "chai"; 3 | import { parseUnits } from "ethers/lib/utils"; 4 | import { ethers } from "hardhat"; 5 | 6 | import { ADDRESSES } from "../helpers/deploymentConfig"; 7 | import { BEP20Harness, IStETH, ResilientOracleInterface } from "../typechain-types"; 8 | import { addr0000 } from "./utils/data"; 9 | 10 | const { expect } = chai; 11 | chai.use(smock.matchers); 12 | 13 | const WSTETH = ADDRESSES.ethereum.wstETHAddress; 14 | const STETH_USD_PRICE = parseUnits("1500", 18); // 1500 USD for 1 stETH 15 | const PRICE_DENOMINATOR = parseUnits("1", 18); 16 | const STETH_AMOUNT_FOR_ONE_WSTETH = parseUnits("1.15", 18); // 1.5 stETH for 1 wETH 17 | 18 | describe("WstETHOracleV2 unit tests", () => { 19 | let stETHMock; 20 | let resilientOracleMock; 21 | let wstETHOracle; 22 | let WsETHOracleFactory; 23 | let wstETHMock; 24 | before(async () => { 25 | // To initialize the provider we need to hit the node with any request 26 | await ethers.getSigners(); 27 | resilientOracleMock = await smock.fake("ResilientOracleInterface"); 28 | 29 | wstETHMock = await smock.fake("BEP20Harness", { address: WSTETH }); 30 | wstETHMock.decimals.returns(18); 31 | 32 | stETHMock = await smock.fake("IStETH"); 33 | stETHMock.getPooledEthByShares.returns(STETH_AMOUNT_FOR_ONE_WSTETH); 34 | stETHMock.decimals.returns(18); 35 | WsETHOracleFactory = await ethers.getContractFactory("WstETHOracleV2"); 36 | 37 | resilientOracleMock.getPrice.returns(STETH_USD_PRICE); 38 | }); 39 | 40 | describe("deployment", () => { 41 | it("revert if wstETH address is 0", async () => { 42 | await expect(WsETHOracleFactory.deploy(addr0000, stETHMock.address, resilientOracleMock.address)).to.be.reverted; 43 | }); 44 | it("revert if stETH address is 0", async () => { 45 | await expect(WsETHOracleFactory.deploy(WSTETH, addr0000, resilientOracleMock.address)).to.be.reverted; 46 | }); 47 | it("revert if ResilientOracle address is 0", async () => { 48 | await expect(WsETHOracleFactory.deploy(WSTETH, stETHMock.address, addr0000)).to.be.reverted; 49 | }); 50 | it("should deploy contract", async () => { 51 | wstETHOracle = await WsETHOracleFactory.deploy(WSTETH, stETHMock.address, resilientOracleMock.address); 52 | }); 53 | }); 54 | 55 | describe("getPrice", () => { 56 | it("revert if wstETH address is wrong", async () => { 57 | await expect(wstETHOracle.getPrice(addr0000)).to.be.revertedWithCustomError(wstETHOracle, "InvalidTokenAddress"); 58 | }); 59 | 60 | it("should get correct price", async () => { 61 | const expectedPrice = STETH_USD_PRICE.mul(STETH_AMOUNT_FOR_ONE_WSTETH).div(PRICE_DENOMINATOR); 62 | expect(await wstETHOracle.getPrice(WSTETH)).to.equal(expectedPrice); 63 | }); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /test/ZkETHOracle.ts: -------------------------------------------------------------------------------- 1 | import { FakeContract, smock } from "@defi-wonderland/smock"; 2 | import chai from "chai"; 3 | import { parseUnits } from "ethers/lib/utils"; 4 | import { ethers } from "hardhat"; 5 | 6 | import { ADDRESSES } from "../helpers/deploymentConfig"; 7 | import { BEP20Harness, IZkETH, ResilientOracleInterface, ZkETHOracle, ZkETHOracle__factory } from "../typechain-types"; 8 | import { addr0000 } from "./utils/data"; 9 | 10 | const { expect } = chai; 11 | chai.use(smock.matchers); 12 | 13 | const { WETH, zkETH } = ADDRESSES.zksyncmainnet; 14 | const WETH_USD_PRICE = parseUnits("2700", 18); 15 | 16 | describe("ZkETHOracle", () => { 17 | let zkETHMock: FakeContract; 18 | let resilientOracleMock: FakeContract; 19 | let zkETHOracleFactory: ZkETHOracle__factory; 20 | let zkETHOracle: ZkETHOracle; 21 | let wethMock: FakeContract; 22 | 23 | before(async () => { 24 | // To initialize the provider we need to hit the node with any request 25 | await ethers.getSigners(); 26 | resilientOracleMock = await smock.fake("ResilientOracleInterface"); 27 | 28 | zkETHMock = await smock.fake("IZkETH", { address: zkETH }); 29 | zkETHMock.LSTPerToken.returns(parseUnits("1.1", 18)); 30 | zkETHMock.decimals.returns(18); 31 | 32 | wethMock = await smock.fake("BEP20Harness", { address: WETH }); 33 | wethMock.decimals.returns(18); 34 | 35 | zkETHOracleFactory = await ethers.getContractFactory("ZkETHOracle"); 36 | }); 37 | 38 | describe("deployment", () => { 39 | it("revert if WETH address is 0", async () => { 40 | await expect(zkETHOracleFactory.deploy(zkETHMock.address, addr0000, resilientOracleMock.address)).to.be.reverted; 41 | }); 42 | 43 | it("revert if zkETH address is 0", async () => { 44 | await expect(zkETHOracleFactory.deploy(addr0000, wethMock.address, resilientOracleMock.address)).to.be.reverted; 45 | }); 46 | 47 | it("should deploy contract", async () => { 48 | zkETHOracle = await zkETHOracleFactory.deploy(zkETHMock.address, wethMock.address, resilientOracleMock.address); 49 | }); 50 | }); 51 | 52 | describe("getPrice", () => { 53 | it("revert if address is not valid zkETH address", async () => { 54 | await expect(zkETHOracle.getPrice(addr0000)).to.be.revertedWithCustomError(zkETHOracle, "InvalidTokenAddress"); 55 | }); 56 | 57 | it("should get correct price of zkETH", async () => { 58 | resilientOracleMock.getPrice.returns(WETH_USD_PRICE); 59 | const price = await zkETHOracle.getPrice(zkETHMock.address); 60 | expect(price).to.equal(parseUnits("2970", 18)); 61 | }); 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /test/asBNBOracle.ts: -------------------------------------------------------------------------------- 1 | import { smock } from "@defi-wonderland/smock"; 2 | import chai from "chai"; 3 | import { parseUnits } from "ethers/lib/utils"; 4 | import { ethers } from "hardhat"; 5 | 6 | import { ADDRESSES } from "../helpers/deploymentConfig"; 7 | import { BEP20Harness, IAsBNBMinter, ResilientOracleInterface } from "../typechain-types"; 8 | import { addr0000 } from "./utils/data"; 9 | 10 | const { expect } = chai; 11 | chai.use(smock.matchers); 12 | 13 | const { asBNB, slisBNB } = ADDRESSES.bscmainnet; 14 | const slisBNB_USD_PRICE = parseUnits("300", 18); // 300 USD for 1 slisBNB 15 | const slisBNB_FOR_ONE_asBNB = parseUnits("1.082798704659082054", 18); 16 | 17 | describe("BNBxOracle unit tests", () => { 18 | let asBNBMinterMock; 19 | let resilientOracleMock; 20 | let asBNBOracle; 21 | let asBNBOracleFactory; 22 | let asBNBMock; 23 | let slisBNBMock; 24 | before(async () => { 25 | // To initialize the provider we need to hit the node with any request 26 | await ethers.getSigners(); 27 | resilientOracleMock = await smock.fake("ResilientOracleInterface"); 28 | resilientOracleMock.getPrice.returns(slisBNB_USD_PRICE); 29 | 30 | asBNBMinterMock = await smock.fake("IAsBNBMinter"); 31 | asBNBMinterMock.convertToTokens.returns(slisBNB_FOR_ONE_asBNB); 32 | 33 | asBNBMock = await smock.fake("IAsBNB", { address: asBNB }); 34 | asBNBMock.decimals.returns(18); 35 | asBNBMock.minter.returns(asBNBMinterMock.address); 36 | 37 | asBNBOracleFactory = await ethers.getContractFactory("AsBNBOracle"); 38 | 39 | slisBNBMock = await smock.fake("BEP20Harness", { address: slisBNB }); 40 | slisBNBMock.decimals.returns(18); 41 | }); 42 | 43 | describe("deployment", () => { 44 | it("revert if asBNB address is 0", async () => { 45 | await expect(asBNBOracleFactory.deploy(addr0000, slisBNBMock.address, resilientOracleMock.address)).to.be 46 | .reverted; 47 | }); 48 | it("revert if slisBNB address is 0", async () => { 49 | await expect(asBNBOracleFactory.deploy(asBNBMock.address, addr0000, resilientOracleMock.address)).to.be.reverted; 50 | }); 51 | it("should deploy contract", async () => { 52 | asBNBOracle = await asBNBOracleFactory.deploy( 53 | asBNBMock.address, 54 | slisBNBMock.address, 55 | resilientOracleMock.address, 56 | ); 57 | }); 58 | }); 59 | 60 | describe("getPrice", () => { 61 | it("revert if asBNB address is wrong", async () => { 62 | await expect(asBNBOracle.getPrice(addr0000)).to.be.revertedWithCustomError(asBNBOracle, "InvalidTokenAddress"); 63 | }); 64 | 65 | it("should get correct price", async () => { 66 | expect(await asBNBOracle.getPrice(asBNB)).to.equal(parseUnits("324.839611397724616200", 18)); 67 | }); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /test/fork/utils.ts: -------------------------------------------------------------------------------- 1 | import { impersonateAccount, setBalance } from "@nomicfoundation/hardhat-network-helpers"; 2 | import { ethers, network } from "hardhat"; 3 | 4 | async function setForkBlock(blockNumber: number) { 5 | await network.provider.request({ 6 | method: "hardhat_reset", 7 | params: [ 8 | { 9 | forking: { 10 | jsonRpcUrl: process.env[`ARCHIVE_NODE_${process.env.FORKED_NETWORK}`], 11 | blockNumber, 12 | }, 13 | }, 14 | ], 15 | }); 16 | } 17 | 18 | export const forking = (blockNumber: number, fn: () => void) => { 19 | describe(`At block #${blockNumber}`, () => { 20 | before(async () => { 21 | await setForkBlock(blockNumber); 22 | }); 23 | fn(); 24 | }); 25 | }; 26 | 27 | export const initMainnetUser = async (user: string, balance: NumberLike) => { 28 | await impersonateAccount(user); 29 | await setBalance(user, balance); 30 | return ethers.getSigner(user); 31 | }; 32 | -------------------------------------------------------------------------------- /test/fork/validate-price-config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-syntax */ 2 | import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/dist/src/signer-with-address"; 3 | import { Contract } from "ethers"; 4 | import { ethers } from "hardhat"; 5 | 6 | import { contracts as bscmainnet } from "../../deployments/bscmainnet.json"; 7 | import { contracts as bsctestnet } from "../../deployments/bsctestnet.json"; 8 | import { contracts as sepolia } from "../../deployments/sepolia.json"; 9 | import { assets } from "../../helpers/deploymentConfig"; 10 | import { forking } from "./utils"; 11 | 12 | const VALID = "\u2705"; // Unicode character for checkmark 13 | const INVALID = "\u274c"; // Unicode character for X mark 14 | const FORK: boolean = process.env.FORK === "true"; 15 | const FORKED_NETWORK: string = process.env.FORKED_NETWORK || ""; 16 | 17 | const oracleAddress = { 18 | bsctestnet: bsctestnet.ResilientOracle.address, 19 | sepolia: sepolia.ResilientOracle.address, 20 | bscmainnet: bscmainnet.ResilientOracle.address, 21 | }; 22 | 23 | type FakeVtokenInfo = { 24 | address: string; 25 | name: string; 26 | }; 27 | 28 | type PriceResult = { 29 | asset: string; 30 | validPrice: string; 31 | errorReason: string; 32 | }; 33 | 34 | type BlockConfig = { 35 | [key: string]: number; 36 | }; 37 | 38 | const blockNumberPerNetwork: BlockConfig = { 39 | bscmainnet: 27541139, 40 | bsctestnet: 29044518, 41 | sepolia: 4744320, 42 | }; 43 | 44 | const blockNumer = blockNumberPerNetwork[FORKED_NETWORK]; 45 | 46 | // NOTE: in order to test the configuration, the blockNumber should be after the configuration transaction took place 47 | if (FORK) { 48 | forking(blockNumer, () => { 49 | let oracle: Contract; 50 | let admin: SignerWithAddress; 51 | let VBep20HarnessFactory; 52 | let fakeVTokens: Array; 53 | describe(`Price configuration validation for network ${FORKED_NETWORK}`, () => { 54 | before(async () => { 55 | fakeVTokens = []; 56 | [admin] = await ethers.getSigners(); 57 | oracle = await ethers.getContractAt("ResilientOracle", oracleAddress[FORKED_NETWORK]); 58 | VBep20HarnessFactory = await ethers.getContractFactory("VBEP20Harness", admin); 59 | for (const asset of assets[FORKED_NETWORK]) { 60 | console.log(`Deploying mock vToken for asset ${asset.token}`); 61 | const vBep20 = await VBep20HarnessFactory.deploy(asset.token, asset.token, 18, asset.address); 62 | const tokenInfo: FakeVtokenInfo = { 63 | address: vBep20.address, 64 | name: asset.token, 65 | }; 66 | fakeVTokens.push(tokenInfo); 67 | } 68 | }); 69 | 70 | it("Validate config for each asset", async () => { 71 | const results: PriceResult[] = []; 72 | let priceResult: PriceResult; 73 | for (const fakeVToken of fakeVTokens) { 74 | try { 75 | console.log(`Checking price for ${fakeVToken.name}...`); 76 | await oracle.getUnderlyingPrice(fakeVToken.address); 77 | priceResult = { 78 | asset: fakeVToken.name, 79 | validPrice: VALID, 80 | errorReason: "N/A", 81 | }; 82 | console.log(`Valid`); 83 | results.push(priceResult); 84 | } catch (err) { 85 | priceResult = { 86 | asset: fakeVToken.name, 87 | validPrice: INVALID, 88 | errorReason: err.reason, 89 | }; 90 | console.log(`Invalid`); 91 | results.push(priceResult); 92 | } 93 | } 94 | console.table(results, ["asset", "validPrice", "errorReason"]); 95 | }).timeout(1000000); 96 | }); 97 | }); 98 | } 99 | -------------------------------------------------------------------------------- /test/fork/wstETHOracle.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-syntax */ 2 | import { smock } from "@defi-wonderland/smock"; 3 | import chai from "chai"; 4 | import { Contract } from "ethers"; 5 | import { parseUnits } from "ethers/lib/utils"; 6 | import { ethers, upgrades } from "hardhat"; 7 | 8 | import { contracts as ethereum } from "../../deployments/ethereum.json"; 9 | import { contracts as sepolia } from "../../deployments/sepolia.json"; 10 | import { ADDRESSES, assets } from "../../helpers/deploymentConfig"; 11 | import { ResilientOracle, WstETHOracle__factory } from "../../typechain-types"; 12 | import { TokenConfigStruct } from "../../typechain-types/contracts/ResilientOracle"; 13 | import { WstETHOracle } from "../../typechain-types/contracts/oracles/WstETHOracle"; 14 | import { addr0000 } from "../utils/data"; 15 | import WSTETH_ABI from "./abi/wstETH.json"; 16 | import { forking, initMainnetUser } from "./utils"; 17 | 18 | const { expect } = chai; 19 | chai.use(smock.matchers); 20 | 21 | type BlockConfig = { 22 | [key: string]: number; 23 | }; 24 | 25 | const FORK: boolean = process.env.FORK === "true"; 26 | const FORKED_NETWORK: string = process.env.FORKED_NETWORK || ""; 27 | const WETH_USD_PRICE_DENOMINATOR = parseUnits("1", 18); 28 | 29 | // NOTE: in order to test the configuration, the blockNumber should be after the configuration transaction took place 30 | if (FORK && (FORKED_NETWORK === "ethereum" || FORKED_NETWORK === "sepolia")) { 31 | const oracleAddress = { 32 | ethereum: ethereum.ResilientOracle.address, 33 | sepolia: sepolia.ResilientOracle.address, 34 | }; 35 | 36 | const { stETHAddress, wstETHAddress, timelock } = ADDRESSES[FORKED_NETWORK]; 37 | 38 | const WETHAsset = assets[FORKED_NETWORK].find(asset => asset.token === "WETH"); 39 | const WETHAddress = WETHAsset?.address ?? addr0000; 40 | 41 | const blockNumberPerNetwork: BlockConfig = { 42 | ethereum: 19000000, 43 | sepolia: 5000000, 44 | }; 45 | 46 | const blockNumer = blockNumberPerNetwork[FORKED_NETWORK]; 47 | forking(blockNumer, () => { 48 | let oracle: ResilientOracle; 49 | let wstETHOracle: WstETHOracle; 50 | let wstETH: Contract; 51 | describe(`Price configuration validation for network ${FORKED_NETWORK}`, () => { 52 | before(async () => { 53 | oracle = await ethers.getContractAt("ResilientOracle", oracleAddress[FORKED_NETWORK]); 54 | wstETH = await ethers.getContractAt(WSTETH_ABI, wstETHAddress); 55 | const WstETHOracleFactory: WstETHOracle__factory = await ethers.getContractFactory("WstETHOracle"); 56 | wstETHOracle = await upgrades.deployProxy(WstETHOracleFactory, [], { 57 | constructorArgs: [wstETHAddress, WETHAddress, stETHAddress, oracle.address], 58 | }); 59 | const impersonatedContractAdmin = await initMainnetUser(timelock, ethers.utils.parseUnits("2")); 60 | 61 | const tokenConfig: TokenConfigStruct = { 62 | asset: wstETHAddress, 63 | oracles: [wstETHOracle.address, addr0000, addr0000], 64 | enableFlagsForOracles: [true, false, false], 65 | }; 66 | 67 | await oracle.connect(impersonatedContractAdmin).setTokenConfig(tokenConfig); 68 | }); 69 | 70 | it("Validate price for wstETH", async () => { 71 | const WETH_USD_PRICE = await oracle.getPrice(WETHAddress); 72 | const STETH_AMOUNT_FOR_ONE_WSTETH = await wstETH.stEthPerToken(); 73 | const expectedPrice = WETH_USD_PRICE.mul(STETH_AMOUNT_FOR_ONE_WSTETH).div(WETH_USD_PRICE_DENOMINATOR); 74 | expect(await oracle.getPrice(wstETHAddress)).to.equal(expectedPrice); 75 | }); 76 | }); 77 | }); 78 | } 79 | -------------------------------------------------------------------------------- /test/types.ts: -------------------------------------------------------------------------------- 1 | import type { SignerWithAddress } from "@nomiclabs/hardhat-ethers/dist/src/signer-with-address"; 2 | 3 | import { BoundValidator, PythOracle } from "../typechain-types"; 4 | import { ResilientOracle } from "../typechain-types/contracts/ResilientOracle"; 5 | import { ChainlinkOracle } from "../typechain-types/contracts/oracles/ChainlinkOracle"; 6 | import { MockPyth } from "../typechain-types/contracts/test/MockPyth"; 7 | import { PancakePairHarness } from "../typechain-types/contracts/test/PancakePairHarness"; 8 | 9 | declare module "mocha" { 10 | export interface Context { 11 | // oracle plugin tests 12 | oracleBasement: ResilientOracle; 13 | // chainlink oracle tests 14 | chainlinkOracle: ChainlinkOracle; 15 | // twap oracle tests 16 | simplePair: PancakePairHarness; 17 | bnbBasedPair: PancakePairHarness; 18 | bnbPair: PancakePairHarness; 19 | // bound validator tests 20 | boundValidator: BoundValidator; 21 | signers: SignerWithAddress[]; 22 | admin: SignerWithAddress; 23 | // pyth oracle 24 | pythOracle: PythOracle; 25 | underlyingPythOracle: MockPyth; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /test/utils/data.ts: -------------------------------------------------------------------------------- 1 | export const addr0000 = "0x0000000000000000000000000000000000000000"; 2 | export const addr1111 = "0x1111111111111111111111111111111111111111"; 3 | export const getSimpleAddress = (i: number) => 4 | `0x${Array.from({ length: 40 }) 5 | .map(() => `${i}`) 6 | .join("")}`; 7 | 8 | export const getBytes32String = (i: number) => 9 | `0x${Array.from({ length: 64 }) 10 | .map(() => `${i}`) 11 | .join("")}`; 12 | -------------------------------------------------------------------------------- /test/utils/makeChainlinkOracle.ts: -------------------------------------------------------------------------------- 1 | import { deployments, ethers, getNamedAccounts } from "hardhat"; 2 | 3 | import { VBEP20Harness } from "../../typechain-types"; 4 | import { ChainlinkOracle } from "../../typechain-types/contracts/oracles/ChainlinkOracle"; 5 | 6 | export const makeChainlinkOracle = async (decimals: number, initialAnswer: number) => { 7 | const { deployer } = await getNamedAccounts(); 8 | const { deploy } = deployments; 9 | const oracle = await deploy("MockV3Aggregator", { 10 | from: deployer, 11 | contract: "MockV3Aggregator", 12 | args: [decimals, initialAnswer], 13 | autoMine: true, 14 | log: true, 15 | }); 16 | const oracleContract = await ethers.getContractAt("MockV3Aggregator", oracle.address); 17 | return oracleContract; 18 | }; 19 | 20 | export const makeVToken = async (name: string, symbol: string, underlying?: string) => { 21 | const { deployer } = await getNamedAccounts(); 22 | const { deploy } = deployments; 23 | let underlyingToken = underlying; 24 | if (!underlying) { 25 | const token = await deploy(`MockV3Aggregator-${name}`, { 26 | from: deployer, 27 | contract: "MockV3Aggregator", 28 | args: [name, symbol], 29 | autoMine: true, 30 | log: true, 31 | }); 32 | underlyingToken = token.address; 33 | } 34 | 35 | const vToken = await deploy(`VBep20Harness-${name}`, { 36 | from: deployer, 37 | contract: "VBep20Harness", 38 | args: [name, symbol, underlyingToken], 39 | autoMine: true, 40 | log: true, 41 | }); 42 | const vTokenContract = await ethers.getContractAt("VBEP20Harness", vToken.address); 43 | return vTokenContract; 44 | }; 45 | -------------------------------------------------------------------------------- /test/utils/makePair.ts: -------------------------------------------------------------------------------- 1 | import { deployments, ethers, getNamedAccounts } from "hardhat"; 2 | 3 | export const makePairWithTokens = async ( 4 | token1: string, 5 | token2: string, 6 | initReserves: [number, number] = [100, 100], 7 | ) => { 8 | const { deployer } = await getNamedAccounts(); 9 | const { deploy } = deployments; 10 | const pair = await deploy(`PancakePairHarness-${token1}-${token2}`, { 11 | from: deployer, 12 | contract: "PancakePairHarness", 13 | args: [], 14 | autoMine: true, 15 | log: true, 16 | }); 17 | const pairContract = await ethers.getContractAt("PancakePairHarness", pair.address); 18 | 19 | await pairContract.initialize(token1, token2); 20 | await pairContract.update(initReserves[0], initReserves[1], initReserves[0], initReserves[1]); 21 | return pairContract; 22 | }; 23 | -------------------------------------------------------------------------------- /test/utils/makeToken.ts: -------------------------------------------------------------------------------- 1 | import { deployments, getNamedAccounts } from "hardhat"; 2 | 3 | export const makeToken = async (name: string, symbol: string, decimals: number = 18) => { 4 | const { deployer } = await getNamedAccounts(); 5 | const { deploy } = deployments; 6 | // make underlying 7 | const token = await deploy(`BEP20Harness-${name}`, { 8 | from: deployer, 9 | contract: "BEP20Harness", 10 | args: [name, symbol, decimals], 11 | autoMine: true, 12 | log: true, 13 | }); 14 | return token; 15 | }; 16 | -------------------------------------------------------------------------------- /test/utils/makeVToken.ts: -------------------------------------------------------------------------------- 1 | import { deployments, ethers, getNamedAccounts } from "hardhat"; 2 | 3 | import { VBEP20Harness } from "../../typechain-types"; 4 | 5 | export const makeVToken = async ( 6 | opts: { name: string; symbol: string; decimals?: number }, 7 | underlyingOpts?: { 8 | symbol: string; 9 | decimals?: number; 10 | name: string; 11 | }, 12 | ) => { 13 | const { deployer } = await getNamedAccounts(); 14 | const { deploy } = deployments; 15 | const underlyingOpts2 = underlyingOpts || { 16 | symbol: "underlyingSymbol", 17 | decimals: 18, 18 | name: "underlyingName", 19 | }; 20 | // make underlying 21 | const underlyingToken = await deploy(`BEP20Harness-${underlyingOpts2.name}`, { 22 | from: deployer, 23 | contract: "BEP20Harness", 24 | args: [underlyingOpts2.name, underlyingOpts2.symbol, underlyingOpts2.decimals || 18], 25 | autoMine: true, 26 | log: true, 27 | }); 28 | 29 | const vToken = await deploy(`VBEP20Harness-${opts.name}`, { 30 | from: deployer, 31 | contract: "VBEP20Harness", 32 | args: [opts.name, opts.symbol, opts.decimals || 8, underlyingToken.address], 33 | autoMine: true, 34 | log: true, 35 | }); 36 | const vTokenContract = await ethers.getContractAt("VBEP20Harness", vToken.address); 37 | return vTokenContract; 38 | }; 39 | -------------------------------------------------------------------------------- /test/utils/time.ts: -------------------------------------------------------------------------------- 1 | import { ethers, network } from "hardhat"; 2 | 3 | export const increaseTime = async (time: number) => { 4 | await network.provider.send("evm_increaseTime", [time]); 5 | await network.provider.send("evm_mine"); // this one will have 02:00 PM as its timestamp 6 | }; 7 | 8 | export const getTime = async () => { 9 | const block = await ethers.provider.getBlock("latest"); 10 | return block.timestamp; 11 | }; 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "declaration": true, 5 | "declarationMap": true, 6 | "emitDecoratorMetadata": true, 7 | "esModuleInterop": true, 8 | "experimentalDecorators": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "lib": ["es2020"], 11 | "module": "commonjs", 12 | "moduleResolution": "node", 13 | "noImplicitAny": true, 14 | "removeComments": true, 15 | "resolveJsonModule": true, 16 | "sourceMap": true, 17 | "strict": true, 18 | "target": "es2020", 19 | "outDir": "dist", 20 | "paths": { 21 | "@nomiclabs/hardhat-ethers": ["node_modules/hardhat-deploy-ethers"] 22 | } 23 | }, 24 | "exclude": ["node_modules"], 25 | "files": ["./hardhat.config.ts"], 26 | "include": ["deploy"] 27 | } 28 | --------------------------------------------------------------------------------