diff --git a/deploy/27-deploy-clisBNB-pendle-oracle.ts b/deploy/27-deploy-clisBNB-pendle-oracle.ts new file mode 100644 index 00000000..8646b349 --- /dev/null +++ b/deploy/27-deploy-clisBNB-pendle-oracle.ts @@ -0,0 +1,79 @@ +import { ethers } from "hardhat"; +import { DeployFunction } from "hardhat-deploy/dist/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; + +import { ADDRESSES } from "../helpers/deploymentConfig"; +import { isMainnet } from "../helpers/deploymentUtils"; + +enum PendleRateKind { + PT_TO_ASSET = 0, + PT_TO_SY = 1, +} + +const func: DeployFunction = async ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) => { + const { deploy } = deployments; + const { deployer } = await getNamedAccounts(); + + const resilientOracle = await ethers.getContract("ResilientOracle"); + const addresses = ADDRESSES[network.name]; + const ptOracleAddress = addresses.PTOracle || (await ethers.getContract("MockPendlePtOracle")).address; + + const commonParams = { + from: deployer, + log: true, + deterministicDeployment: false, + skipIfAlreadyDeployed: true, + waitConfirmations: 1, + }; + + await deploy("PendleOracle-PT-clisBNB-25JUN2026", { + contract: "PendleOracle", + args: [ + { + market: addresses["PT-clisBNB-25JUN2026_Market"] || "0x0000000000000000000000000000000000000004", + ptOracle: ptOracleAddress, + rateKind: PendleRateKind.PT_TO_SY, + ptToken: addresses["PT-clisBNB-25JUN2026"], + underlyingToken: addresses.slisBNB, + resilientOracle: resilientOracle.address, + twapDuration: 1800, + annualGrowthRate: 0, + snapshotInterval: 0, + initialSnapshotMaxExchangeRate: 0, + initialSnapshotTimestamp: 0, + accessControlManager: addresses.acm, + snapshotGap: 0, + }, + ], + ...commonParams, + }); + + if (isMainnet(network)) { + await deploy("PendleOracle-PT-clisBNB-25JUN2026_Reference_PtToAsset", { + contract: "PendleOracle", + args: [ + { + market: addresses["PT-clisBNB-25JUN2026_Market"] || "0x0000000000000000000000000000000000000002", + ptOracle: ptOracleAddress, + rateKind: PendleRateKind.PT_TO_ASSET, + ptToken: addresses["PT-clisBNB-25JUN2026"], + underlyingToken: addresses.slisBNB, + resilientOracle: resilientOracle.address, + twapDuration: 1800, + annualGrowthRate: 0, + snapshotInterval: 0, + initialSnapshotMaxExchangeRate: 0, + initialSnapshotTimestamp: 0, + accessControlManager: addresses.acm, + snapshotGap: 0, + }, + ], + ...commonParams, + }); + } +}; + +export default func; +func.tags = ["PT-clisBNB-2026"]; +func.skip = async (hre: HardhatRuntimeEnvironment) => + hre.network.name !== "bsctestnet" && hre.network.name !== "bscmainnet"; diff --git a/deployments/bscmainnet.json b/deployments/bscmainnet.json index c565f483..95171c0d 100644 --- a/deployments/bscmainnet.json +++ b/deployments/bscmainnet.json @@ -8077,6 +8077,1014 @@ } ] }, + "PendleOracle-PT-clisBNB-25JUN2026": { + "address": "0x0FfFBb55d51cD46cD10C7dc865Dc73BD76201310", + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "address", + "name": "ptOracle", + "type": "address" + }, + { + "internalType": "enum PendleOracle.RateKind", + "name": "rateKind", + "type": "uint8" + }, + { + "internalType": "address", + "name": "ptToken", + "type": "address" + }, + { + "internalType": "address", + "name": "underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "resilientOracle", + "type": "address" + }, + { + "internalType": "uint32", + "name": "twapDuration", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "annualGrowthRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "snapshotInterval", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSnapshotMaxExchangeRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSnapshotTimestamp", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager", + "type": "address" + }, + { + "internalType": "uint256", + "name": "snapshotGap", + "type": "uint256" + } + ], + "internalType": "struct PendleOracle.ConstructorParams", + "name": "params", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidDuration", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidGrowthRate", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialSnapshot", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSnapshotMaxExchangeRate", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTokenAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValueNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldGrowthRatePerSecond", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newGrowthRatePerSecond", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "oldSnapshotInterval", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSnapshotInterval", + "type": "uint256" + } + ], + "name": "GrowthRateUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldSnapshotGap", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newSnapshotGap", + "type": "uint256" + } + ], + "name": "SnapshotGapUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "maxExchangeRate", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "SnapshotUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "ACCESS_CONTROL_MANAGER", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CORRELATED_TOKEN", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MARKET", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PT_ORACLE", + "outputs": [ + { + "internalType": "contract IPendlePtOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RATE_KIND", + "outputs": [ + { + "internalType": "enum PendleOracle.RateKind", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESILIENT_ORACLE", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TWAP_DURATION", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNDERLYING_DECIMALS", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNDERLYING_TOKEN", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxAllowedExchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUnderlyingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "growthRatePerSecond", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isCapped", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_annualGrowthRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_snapshotInterval", + "type": "uint256" + } + ], + "name": "setGrowthRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_snapshotMaxExchangeRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_snapshotTimestamp", + "type": "uint256" + } + ], + "name": "setSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_snapshotGap", + "type": "uint256" + } + ], + "name": "setSnapshotGap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotGap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotInterval", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotMaxExchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "updateSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "PendleOracle-PT-clisBNB-25JUN2026_Reference_PtToAsset": { + "address": "0xc94866f155FEA46C398385665B08B813D20DF802", + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "address", + "name": "ptOracle", + "type": "address" + }, + { + "internalType": "enum PendleOracle.RateKind", + "name": "rateKind", + "type": "uint8" + }, + { + "internalType": "address", + "name": "ptToken", + "type": "address" + }, + { + "internalType": "address", + "name": "underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "resilientOracle", + "type": "address" + }, + { + "internalType": "uint32", + "name": "twapDuration", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "annualGrowthRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "snapshotInterval", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSnapshotMaxExchangeRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSnapshotTimestamp", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager", + "type": "address" + }, + { + "internalType": "uint256", + "name": "snapshotGap", + "type": "uint256" + } + ], + "internalType": "struct PendleOracle.ConstructorParams", + "name": "params", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidDuration", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidGrowthRate", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialSnapshot", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSnapshotMaxExchangeRate", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTokenAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValueNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldGrowthRatePerSecond", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newGrowthRatePerSecond", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "oldSnapshotInterval", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSnapshotInterval", + "type": "uint256" + } + ], + "name": "GrowthRateUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldSnapshotGap", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newSnapshotGap", + "type": "uint256" + } + ], + "name": "SnapshotGapUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "maxExchangeRate", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "SnapshotUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "ACCESS_CONTROL_MANAGER", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CORRELATED_TOKEN", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MARKET", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PT_ORACLE", + "outputs": [ + { + "internalType": "contract IPendlePtOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RATE_KIND", + "outputs": [ + { + "internalType": "enum PendleOracle.RateKind", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESILIENT_ORACLE", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TWAP_DURATION", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNDERLYING_DECIMALS", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNDERLYING_TOKEN", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxAllowedExchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUnderlyingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "growthRatePerSecond", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isCapped", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_annualGrowthRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_snapshotInterval", + "type": "uint256" + } + ], + "name": "setGrowthRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_snapshotMaxExchangeRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_snapshotTimestamp", + "type": "uint256" + } + ], + "name": "setSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_snapshotGap", + "type": "uint256" + } + ], + "name": "setSnapshotGap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotGap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotInterval", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotMaxExchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "updateSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, "PendleOracle-PT-sUSDe-26JUN2025": { "address": "0xC407403fa78Bce509821D776b6Be7f91cC04474f", "abi": [ diff --git a/deployments/bscmainnet/PendleOracle-PT-clisBNB-25JUN2026.json b/deployments/bscmainnet/PendleOracle-PT-clisBNB-25JUN2026.json new file mode 100644 index 00000000..9428189b --- /dev/null +++ b/deployments/bscmainnet/PendleOracle-PT-clisBNB-25JUN2026.json @@ -0,0 +1,785 @@ +{ + "address": "0x0FfFBb55d51cD46cD10C7dc865Dc73BD76201310", + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "address", + "name": "ptOracle", + "type": "address" + }, + { + "internalType": "enum PendleOracle.RateKind", + "name": "rateKind", + "type": "uint8" + }, + { + "internalType": "address", + "name": "ptToken", + "type": "address" + }, + { + "internalType": "address", + "name": "underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "resilientOracle", + "type": "address" + }, + { + "internalType": "uint32", + "name": "twapDuration", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "annualGrowthRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "snapshotInterval", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSnapshotMaxExchangeRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSnapshotTimestamp", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager", + "type": "address" + }, + { + "internalType": "uint256", + "name": "snapshotGap", + "type": "uint256" + } + ], + "internalType": "struct PendleOracle.ConstructorParams", + "name": "params", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidDuration", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidGrowthRate", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialSnapshot", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSnapshotMaxExchangeRate", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTokenAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValueNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldGrowthRatePerSecond", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newGrowthRatePerSecond", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "oldSnapshotInterval", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSnapshotInterval", + "type": "uint256" + } + ], + "name": "GrowthRateUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldSnapshotGap", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newSnapshotGap", + "type": "uint256" + } + ], + "name": "SnapshotGapUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "maxExchangeRate", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "SnapshotUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "ACCESS_CONTROL_MANAGER", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CORRELATED_TOKEN", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MARKET", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PT_ORACLE", + "outputs": [ + { + "internalType": "contract IPendlePtOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RATE_KIND", + "outputs": [ + { + "internalType": "enum PendleOracle.RateKind", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESILIENT_ORACLE", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TWAP_DURATION", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNDERLYING_DECIMALS", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNDERLYING_TOKEN", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxAllowedExchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUnderlyingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "growthRatePerSecond", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isCapped", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_annualGrowthRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_snapshotInterval", + "type": "uint256" + } + ], + "name": "setGrowthRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_snapshotMaxExchangeRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_snapshotTimestamp", + "type": "uint256" + } + ], + "name": "setSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_snapshotGap", + "type": "uint256" + } + ], + "name": "setSnapshotGap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotGap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotInterval", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotMaxExchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "updateSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xab5d3384b04076a77292fb93a537e068e820f3d9f230eadf4ed339c7e5c26588", + "receipt": { + "to": null, + "from": "0x24c30C9C84b8a3C71A521ad30007ED47372331b3", + "contractAddress": "0x0FfFBb55d51cD46cD10C7dc865Dc73BD76201310", + "transactionIndex": 83, + "gasUsed": "969841", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xa795dd42698c0fd1eca9e8159215d99f769e20ccd8d434365197a0bfcb0bcbfa", + "transactionHash": "0xab5d3384b04076a77292fb93a537e068e820f3d9f230eadf4ed339c7e5c26588", + "logs": [], + "blockNumber": 74954029, + "cumulativeGasUsed": "12849775", + "status": 1, + "byzantium": true + }, + "args": [ + { + "market": "0x3C1a3D6B69A866444Fe506F7D38a00a1C2D859C5", + "ptOracle": "0x9a9fa8338dd5e5b2188006f1cd2ef26d921650c2", + "rateKind": 1, + "ptToken": "0xe052823b4aefc6e230FAf46231A57d0905E30AE0", + "underlyingToken": "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B", + "resilientOracle": "0x6592b5DE802159F3E74B2486b091D11a8256ab8A", + "twapDuration": 1800, + "annualGrowthRate": 0, + "snapshotInterval": 0, + "initialSnapshotMaxExchangeRate": 0, + "initialSnapshotTimestamp": 0, + "accessControlManager": "0x4788629abc6cfca10f9f969efdeaa1cf70c23555", + "snapshotGap": 0 + } + ], + "numDeployments": 1, + "solcInputHash": "a5bca20982c9bb49cb2eb7474644c181", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"ptOracle\",\"type\":\"address\"},{\"internalType\":\"enum PendleOracle.RateKind\",\"name\":\"rateKind\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"ptToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"underlyingToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resilientOracle\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"twapDuration\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"annualGrowthRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"snapshotInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"initialSnapshotMaxExchangeRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"initialSnapshotTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"accessControlManager\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"snapshotGap\",\"type\":\"uint256\"}],\"internalType\":\"struct PendleOracle.ConstructorParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidDuration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidGrowthRate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialSnapshot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSnapshotMaxExchangeRate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldGrowthRatePerSecond\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newGrowthRatePerSecond\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldSnapshotInterval\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSnapshotInterval\",\"type\":\"uint256\"}],\"name\":\"GrowthRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldSnapshotGap\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newSnapshotGap\",\"type\":\"uint256\"}],\"name\":\"SnapshotGapUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"maxExchangeRate\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"SnapshotUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ACCESS_CONTROL_MANAGER\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"CORRELATED_TOKEN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MARKET\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PT_ORACLE\",\"outputs\":[{\"internalType\":\"contract IPendlePtOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RATE_KIND\",\"outputs\":[{\"internalType\":\"enum PendleOracle.RateKind\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RESILIENT_ORACLE\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TWAP_DURATION\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UNDERLYING_DECIMALS\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UNDERLYING_TOKEN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getMaxAllowedExchangeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getUnderlyingAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"growthRatePerSecond\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isCapped\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_annualGrowthRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_snapshotInterval\",\"type\":\"uint256\"}],\"name\":\"setGrowthRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_snapshotMaxExchangeRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_snapshotTimestamp\",\"type\":\"uint256\"}],\"name\":\"setSnapshot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_snapshotGap\",\"type\":\"uint256\"}],\"name\":\"setSnapshotGap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"snapshotGap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"snapshotInterval\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"snapshotMaxExchangeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"snapshotTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateSnapshot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"As a base price the oracle uses either the price of the Pendle market's asset (in this case PT_TO_ASSET rate should be used) or the price of the Pendle market's interest bearing token (e.g. wstETH for stETH; in this case PT_TO_SY rate should be used). Technically, interest bearing token is different from standardized yield (SY) token, but since SY is a wrapper around an interest bearing token, we can safely assume the prices of the two are equal. This is not always true for asset price though: using PT_TO_ASSET rate assumes that the yield token can be seamlessly redeemed for the underlying asset. In reality, this might not always be the case. For more details, see https://docs.pendle.finance/Developers/Contracts/StandardizedYield\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:error\":\"InvalidDuration Thrown if the duration is invalid\"},\"getMaxAllowedExchangeRate()\":{\"returns\":{\"_0\":\"maxExchangeRate Maximum allowed exchange rate\"}},\"getPrice(address)\":{\"custom:error\":\"InvalidTokenAddress error is thrown if the token address is invalid\",\"params\":{\"asset\":\"Address of the token\"},\"returns\":{\"_0\":\"price The price of the token in scaled decimal places. It can be capped to a maximum value taking into account the growth rate\"}},\"getUnderlyingAmount()\":{\"returns\":{\"_0\":\"amount The amount of underlying token (either the market's asset or the yield token) for 1 PT, adjusted for decimals such that the result has the same precision as the underlying token\"}},\"isCapped()\":{\"returns\":{\"_0\":\"isCapped Boolean indicating if the price is capped\"}},\"setGrowthRate(uint256,uint256)\":{\"custom:error\":\"InvalidGrowthRate error is thrown if the growth rate is invalid\",\"custom:event\":\"Emits GrowthRateUpdated event on successful update of the growth rate\",\"params\":{\"_annualGrowthRate\":\"The annual growth rate to set\",\"_snapshotInterval\":\"The snapshot interval to set\"}},\"setSnapshot(uint256,uint256)\":{\"custom:event\":\"Emits SnapshotUpdated event on successful update of the snapshot\",\"params\":{\"_snapshotMaxExchangeRate\":\"The exchange rate to set\",\"_snapshotTimestamp\":\"The timestamp to set\"}},\"setSnapshotGap(uint256)\":{\"custom:event\":\"Emits SnapshotGapUpdated event on successful update of the snapshot gap\",\"params\":{\"_snapshotGap\":\"The snapshot gap to set\"}},\"updateSnapshot()\":{\"custom:error\":\"InvalidSnapshotMaxExchangeRate error is thrown if the max snapshot exchange rate is zero\",\"custom:event\":\"Emits SnapshotUpdated event on successful update of the snapshot\"}},\"stateVariables\":{\"UNDERLYING_DECIMALS\":{\"details\":\"We make an assumption that the underlying decimals will not change throughout the lifetime of the Pendle market\"}},\"title\":\"PendleOracle\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidDuration()\":[{\"notice\":\"Thrown if the duration is invalid\"}],\"InvalidGrowthRate()\":[{\"notice\":\"Thrown if the growth rate is invalid\"}],\"InvalidInitialSnapshot()\":[{\"notice\":\"Thrown if the initial snapshot is invalid\"}],\"InvalidSnapshotMaxExchangeRate()\":[{\"notice\":\"Thrown if the max snapshot exchange rate is invalid\"}],\"InvalidTokenAddress()\":[{\"notice\":\"Thrown if the token address is invalid\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"@notice Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"GrowthRateUpdated(uint256,uint256,uint256,uint256)\":{\"notice\":\"Emitted when the growth rate is updated\"},\"SnapshotGapUpdated(uint256,uint256)\":{\"notice\":\"Emitted when the snapshot gap is updated\"},\"SnapshotUpdated(uint256,uint256)\":{\"notice\":\"Emitted when the snapshot is updated\"}},\"kind\":\"user\",\"methods\":{\"ACCESS_CONTROL_MANAGER()\":{\"notice\":\"Address of the AccessControlManager contract\"},\"CORRELATED_TOKEN()\":{\"notice\":\"Address of the correlated token\"},\"MARKET()\":{\"notice\":\"Address of the market\"},\"PT_ORACLE()\":{\"notice\":\"Address of the PT oracle\"},\"RATE_KIND()\":{\"notice\":\"Whether to use PT/SY (standardized yield token) rate or PT/market asset rate\"},\"RESILIENT_ORACLE()\":{\"notice\":\"Address of Resilient Oracle\"},\"TWAP_DURATION()\":{\"notice\":\"Twap duration for the oracle\"},\"UNDERLYING_DECIMALS()\":{\"notice\":\"Decimals of the underlying token\"},\"UNDERLYING_TOKEN()\":{\"notice\":\"Address of the underlying token\"},\"constructor\":{\"notice\":\"Constructor for the implementation contract.\"},\"getMaxAllowedExchangeRate()\":{\"notice\":\"Gets the maximum allowed exchange rate for token\"},\"getPrice(address)\":{\"notice\":\"Fetches the price of the token\"},\"getUnderlyingAmount()\":{\"notice\":\"Fetches the amount of underlying token for 1 PT\"},\"isCapped()\":{\"notice\":\"Returns if the price is capped\"},\"setGrowthRate(uint256,uint256)\":{\"notice\":\"Sets the growth rate and snapshot interval\"},\"setSnapshot(uint256,uint256)\":{\"notice\":\"Directly sets the snapshot exchange rate and timestamp\"},\"setSnapshotGap(uint256)\":{\"notice\":\"Sets the snapshot gap\"},\"snapshotGap()\":{\"notice\":\"Gap to add when updating the snapshot\"},\"snapshotInterval()\":{\"notice\":\"Snapshot update interval\"},\"snapshotMaxExchangeRate()\":{\"notice\":\"Last stored snapshot maximum exchange rate\"},\"snapshotTimestamp()\":{\"notice\":\"Last stored snapshot timestamp\"},\"updateSnapshot()\":{\"notice\":\"Updates the snapshot price and timestamp\"}},\"notice\":\"This oracle fetches the price of a pendle token\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/oracles/PendleOracle.sol\":\"PendleOracle\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xdb88e14d50dd21889ca3329d755673d022c47e8da005b6a545c7f69c2c4b7b86\",\"license\":\"BSD-3-Clause\"},\"contracts/interfaces/ICappedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface ICappedOracle {\\n function updateSnapshot() external;\\n}\\n\",\"keccak256\":\"0xad239e65b5e92b3486418c5ccca120247702251f9724cd96657c3cfdc7fedc31\",\"license\":\"BSD-3-Clause\"},\"contracts/interfaces/IPendlePtOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IPendlePtOracle {\\n function getPtToAssetRate(address market, uint32 duration) external view returns (uint256);\\n\\n function getPtToSyRate(address market, uint32 duration) external view returns (uint256);\\n\\n function getOracleState(\\n address market,\\n uint32 duration\\n )\\n external\\n view\\n returns (bool increaseCardinalityRequired, uint16 cardinalityRequired, bool oldestObservationSatisfied);\\n}\\n\",\"keccak256\":\"0x14d96d7f75397e4291288ef6367053bd970d95fc0c3e2a028b077f6342e0160a\",\"license\":\"BSD-3-Clause\"},\"contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"contracts/oracles/PendleOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IPendlePtOracle } from \\\"../interfaces/IPendlePtOracle.sol\\\";\\nimport { CorrelatedTokenOracle } from \\\"./common/CorrelatedTokenOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\n/**\\n * @title PendleOracle\\n * @author Venus\\n * @notice This oracle fetches the price of a pendle token\\n * @dev As a base price the oracle uses either the price of the Pendle\\n * market's asset (in this case PT_TO_ASSET rate should be used) or\\n * the price of the Pendle market's interest bearing token (e.g. wstETH\\n * for stETH; in this case PT_TO_SY rate should be used). Technically,\\n * interest bearing token is different from standardized yield (SY) token,\\n * but since SY is a wrapper around an interest bearing token, we can safely\\n * assume the prices of the two are equal. This is not always true for asset\\n * price though: using PT_TO_ASSET rate assumes that the yield token can\\n * be seamlessly redeemed for the underlying asset. In reality, this might\\n * not always be the case. For more details, see\\n * https://docs.pendle.finance/Developers/Contracts/StandardizedYield\\n */\\ncontract PendleOracle is CorrelatedTokenOracle {\\n struct ConstructorParams {\\n /// @notice Pendle market\\n address market;\\n /// @notice Pendle oracle\\n address ptOracle;\\n /// @notice Either PT_TO_ASSET or PT_TO_SY\\n RateKind rateKind;\\n /// @notice Pendle PT token\\n address ptToken;\\n /// @notice Underlying token, can be either the market's asset or the interest bearing token\\n address underlyingToken;\\n /// @notice Resilient oracle to get the underlying token price from\\n address resilientOracle;\\n /// @notice TWAP duration to call Pendle oracle with\\n uint32 twapDuration;\\n /// @notice Annual growth rate of the underlying token\\n uint256 annualGrowthRate;\\n /// @notice Snapshot interval for the oracle\\n uint256 snapshotInterval;\\n /// @notice Initial exchange rate of the underlying token\\n uint256 initialSnapshotMaxExchangeRate;\\n /// @notice Initial timestamp of the underlying token\\n uint256 initialSnapshotTimestamp;\\n /// @notice Access control manager\\n address accessControlManager;\\n /// @notice Gap to add when updating the snapshot\\n uint256 snapshotGap;\\n }\\n\\n /// @notice Which asset to use as a base for the returned PT\\n /// price. Can be either a standardized yield token (SY), in\\n /// this case PT/SY price is returned, or the Pendle\\n /// market's asset directly.\\n enum RateKind {\\n PT_TO_ASSET,\\n PT_TO_SY\\n }\\n\\n /// @notice Address of the PT oracle\\n IPendlePtOracle public immutable PT_ORACLE;\\n\\n /// @notice Whether to use PT/SY (standardized yield token) rate\\n /// or PT/market asset rate\\n RateKind public immutable RATE_KIND;\\n\\n /// @notice Address of the market\\n address public immutable MARKET;\\n\\n /// @notice Twap duration for the oracle\\n uint32 public immutable TWAP_DURATION;\\n\\n /// @notice Decimals of the underlying token\\n /// @dev We make an assumption that the underlying decimals will\\n /// not change throughout the lifetime of the Pendle market\\n uint8 public immutable UNDERLYING_DECIMALS;\\n\\n /// @notice Thrown if the duration is invalid\\n error InvalidDuration();\\n\\n /**\\n * @notice Constructor for the implementation contract.\\n * @custom:error InvalidDuration Thrown if the duration is invalid\\n */\\n constructor(\\n ConstructorParams memory params\\n )\\n CorrelatedTokenOracle(\\n params.ptToken,\\n params.underlyingToken,\\n params.resilientOracle,\\n params.annualGrowthRate,\\n params.snapshotInterval,\\n params.initialSnapshotMaxExchangeRate,\\n params.initialSnapshotTimestamp,\\n params.accessControlManager,\\n params.snapshotGap\\n )\\n {\\n ensureNonzeroAddress(params.market);\\n ensureNonzeroAddress(params.ptOracle);\\n ensureNonzeroValue(params.twapDuration);\\n\\n MARKET = params.market;\\n PT_ORACLE = IPendlePtOracle(params.ptOracle);\\n RATE_KIND = params.rateKind;\\n TWAP_DURATION = params.twapDuration;\\n UNDERLYING_DECIMALS = IERC20Metadata(UNDERLYING_TOKEN).decimals();\\n\\n (bool increaseCardinalityRequired, , bool oldestObservationSatisfied) = PT_ORACLE.getOracleState(\\n MARKET,\\n TWAP_DURATION\\n );\\n if (increaseCardinalityRequired || !oldestObservationSatisfied) {\\n revert InvalidDuration();\\n }\\n }\\n\\n /// @notice Fetches the amount of underlying token for 1 PT\\n /// @return amount The amount of underlying token (either the market's asset\\n /// or the yield token) for 1 PT, adjusted for decimals such that the result\\n /// has the same precision as the underlying token\\n function getUnderlyingAmount() public view override returns (uint256) {\\n uint256 rate;\\n if (RATE_KIND == RateKind.PT_TO_SY) {\\n rate = PT_ORACLE.getPtToSyRate(MARKET, TWAP_DURATION);\\n } else {\\n rate = PT_ORACLE.getPtToAssetRate(MARKET, TWAP_DURATION);\\n }\\n return ((10 ** UNDERLYING_DECIMALS) * rate) / 1e18;\\n }\\n}\\n\",\"keccak256\":\"0xaa7963ac7657ea62079c2162cb4fc45524f8ffbbc6e84f89a5d4e54b71dc6025\",\"license\":\"BSD-3-Clause\"},\"contracts/oracles/common/CorrelatedTokenOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { OracleInterface, ResilientOracleInterface } from \\\"../../interfaces/OracleInterface.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { SECONDS_PER_YEAR } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { ICappedOracle } from \\\"../../interfaces/ICappedOracle.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title CorrelatedTokenOracle\\n * @notice This oracle fetches the price of a token that is correlated to another token.\\n */\\nabstract contract CorrelatedTokenOracle is OracleInterface, ICappedOracle {\\n /// @notice Address of the correlated token\\n address public immutable CORRELATED_TOKEN;\\n\\n /// @notice Address of the underlying token\\n address public immutable UNDERLYING_TOKEN;\\n\\n /// @notice Address of Resilient Oracle\\n ResilientOracleInterface public immutable RESILIENT_ORACLE;\\n\\n /// @notice Address of the AccessControlManager contract\\n IAccessControlManagerV8 public immutable ACCESS_CONTROL_MANAGER;\\n\\n //// @notice Growth rate percentage in seconds. Ex: 1e18 is 100%\\n uint256 public growthRatePerSecond;\\n\\n /// @notice Snapshot update interval\\n uint256 public snapshotInterval;\\n\\n /// @notice Last stored snapshot maximum exchange rate\\n uint256 public snapshotMaxExchangeRate;\\n\\n /// @notice Last stored snapshot timestamp\\n uint256 public snapshotTimestamp;\\n\\n /// @notice Gap to add when updating the snapshot\\n uint256 public snapshotGap;\\n\\n /// @notice Emitted when the snapshot is updated\\n event SnapshotUpdated(uint256 indexed maxExchangeRate, uint256 indexed timestamp);\\n\\n /// @notice Emitted when the growth rate is updated\\n event GrowthRateUpdated(\\n uint256 indexed oldGrowthRatePerSecond,\\n uint256 indexed newGrowthRatePerSecond,\\n uint256 indexed oldSnapshotInterval,\\n uint256 newSnapshotInterval\\n );\\n\\n /// @notice Emitted when the snapshot gap is updated\\n event SnapshotGapUpdated(uint256 indexed oldSnapshotGap, uint256 indexed newSnapshotGap);\\n\\n /// @notice Thrown if the token address is invalid\\n error InvalidTokenAddress();\\n\\n /// @notice Thrown if the growth rate is invalid\\n error InvalidGrowthRate();\\n\\n /// @notice Thrown if the initial snapshot is invalid\\n error InvalidInitialSnapshot();\\n\\n /// @notice Thrown if the max snapshot exchange rate is invalid\\n error InvalidSnapshotMaxExchangeRate();\\n\\n /// @notice @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n /**\\n * @notice Constructor for the implementation contract.\\n * @custom:error InvalidGrowthRate error is thrown if the growth rate is invalid\\n * @custom:error InvalidInitialSnapshot error is thrown if the initial snapshot values are invalid\\n */\\n constructor(\\n address _correlatedToken,\\n address _underlyingToken,\\n address _resilientOracle,\\n uint256 _annualGrowthRate,\\n uint256 _snapshotInterval,\\n uint256 _initialSnapshotMaxExchangeRate,\\n uint256 _initialSnapshotTimestamp,\\n address _accessControlManager,\\n uint256 _snapshotGap\\n ) {\\n growthRatePerSecond = _annualGrowthRate / SECONDS_PER_YEAR;\\n\\n if ((growthRatePerSecond == 0 && _snapshotInterval > 0) || (growthRatePerSecond > 0 && _snapshotInterval == 0))\\n revert InvalidGrowthRate();\\n\\n if ((_initialSnapshotMaxExchangeRate == 0 || _initialSnapshotTimestamp == 0) && _snapshotInterval > 0) {\\n revert InvalidInitialSnapshot();\\n }\\n\\n ensureNonzeroAddress(_correlatedToken);\\n ensureNonzeroAddress(_underlyingToken);\\n ensureNonzeroAddress(_resilientOracle);\\n ensureNonzeroAddress(_accessControlManager);\\n\\n CORRELATED_TOKEN = _correlatedToken;\\n UNDERLYING_TOKEN = _underlyingToken;\\n RESILIENT_ORACLE = ResilientOracleInterface(_resilientOracle);\\n snapshotInterval = _snapshotInterval;\\n\\n snapshotMaxExchangeRate = _initialSnapshotMaxExchangeRate;\\n snapshotTimestamp = _initialSnapshotTimestamp;\\n snapshotGap = _snapshotGap;\\n\\n ACCESS_CONTROL_MANAGER = IAccessControlManagerV8(_accessControlManager);\\n }\\n\\n /**\\n * @notice Directly sets the snapshot exchange rate and timestamp\\n * @param _snapshotMaxExchangeRate The exchange rate to set\\n * @param _snapshotTimestamp The timestamp to set\\n * @custom:event Emits SnapshotUpdated event on successful update of the snapshot\\n */\\n function setSnapshot(uint256 _snapshotMaxExchangeRate, uint256 _snapshotTimestamp) external {\\n _checkAccessAllowed(\\\"setSnapshot(uint256,uint256)\\\");\\n\\n snapshotMaxExchangeRate = _snapshotMaxExchangeRate;\\n snapshotTimestamp = _snapshotTimestamp;\\n\\n emit SnapshotUpdated(snapshotMaxExchangeRate, snapshotTimestamp);\\n }\\n\\n /**\\n * @notice Sets the growth rate and snapshot interval\\n * @param _annualGrowthRate The annual growth rate to set\\n * @param _snapshotInterval The snapshot interval to set\\n * @custom:error InvalidGrowthRate error is thrown if the growth rate is invalid\\n * @custom:event Emits GrowthRateUpdated event on successful update of the growth rate\\n */\\n function setGrowthRate(uint256 _annualGrowthRate, uint256 _snapshotInterval) external {\\n _checkAccessAllowed(\\\"setGrowthRate(uint256,uint256)\\\");\\n uint256 oldGrowthRatePerSecond = growthRatePerSecond;\\n\\n growthRatePerSecond = _annualGrowthRate / SECONDS_PER_YEAR;\\n\\n if ((growthRatePerSecond == 0 && _snapshotInterval > 0) || (growthRatePerSecond > 0 && _snapshotInterval == 0))\\n revert InvalidGrowthRate();\\n\\n emit GrowthRateUpdated(oldGrowthRatePerSecond, growthRatePerSecond, snapshotInterval, _snapshotInterval);\\n\\n snapshotInterval = _snapshotInterval;\\n }\\n\\n /**\\n * @notice Sets the snapshot gap\\n * @param _snapshotGap The snapshot gap to set\\n * @custom:event Emits SnapshotGapUpdated event on successful update of the snapshot gap\\n */\\n function setSnapshotGap(uint256 _snapshotGap) external {\\n _checkAccessAllowed(\\\"setSnapshotGap(uint256)\\\");\\n\\n emit SnapshotGapUpdated(snapshotGap, _snapshotGap);\\n\\n snapshotGap = _snapshotGap;\\n }\\n\\n /**\\n * @notice Returns if the price is capped\\n * @return isCapped Boolean indicating if the price is capped\\n */\\n function isCapped() external view virtual returns (bool) {\\n if (snapshotInterval == 0) {\\n return false;\\n }\\n\\n uint256 maxAllowedExchangeRate = getMaxAllowedExchangeRate();\\n if (maxAllowedExchangeRate == 0) {\\n return false;\\n }\\n\\n uint256 exchangeRate = getUnderlyingAmount();\\n\\n return exchangeRate > maxAllowedExchangeRate;\\n }\\n\\n /**\\n * @notice Updates the snapshot price and timestamp\\n * @custom:event Emits SnapshotUpdated event on successful update of the snapshot\\n * @custom:error InvalidSnapshotMaxExchangeRate error is thrown if the max snapshot exchange rate is zero\\n */\\n function updateSnapshot() public override {\\n if (block.timestamp - snapshotTimestamp < snapshotInterval || snapshotInterval == 0) return;\\n\\n uint256 exchangeRate = getUnderlyingAmount();\\n uint256 maxAllowedExchangeRate = getMaxAllowedExchangeRate();\\n\\n snapshotMaxExchangeRate =\\n (exchangeRate > maxAllowedExchangeRate ? maxAllowedExchangeRate : exchangeRate) +\\n snapshotGap;\\n snapshotTimestamp = block.timestamp;\\n\\n if (snapshotMaxExchangeRate == 0) revert InvalidSnapshotMaxExchangeRate();\\n\\n RESILIENT_ORACLE.updateAssetPrice(UNDERLYING_TOKEN);\\n emit SnapshotUpdated(snapshotMaxExchangeRate, snapshotTimestamp);\\n }\\n\\n /**\\n * @notice Fetches the price of the token\\n * @param asset Address of the token\\n * @return price The price of the token in scaled decimal places. It can be capped\\n * to a maximum value taking into account the growth rate\\n * @custom:error InvalidTokenAddress error is thrown if the token address is invalid\\n */\\n function getPrice(address asset) public view override returns (uint256) {\\n if (asset != CORRELATED_TOKEN) revert InvalidTokenAddress();\\n\\n uint256 exchangeRate = getUnderlyingAmount();\\n\\n if (snapshotInterval == 0) {\\n return _calculatePrice(exchangeRate);\\n }\\n\\n uint256 maxAllowedExchangeRate = getMaxAllowedExchangeRate();\\n\\n uint256 finalExchangeRate = (exchangeRate > maxAllowedExchangeRate && maxAllowedExchangeRate != 0)\\n ? maxAllowedExchangeRate\\n : exchangeRate;\\n\\n return _calculatePrice(finalExchangeRate);\\n }\\n\\n /**\\n * @notice Gets the maximum allowed exchange rate for token\\n * @return maxExchangeRate Maximum allowed exchange rate\\n */\\n function getMaxAllowedExchangeRate() public view returns (uint256) {\\n uint256 timeElapsed = block.timestamp - snapshotTimestamp;\\n uint256 maxExchangeRate = snapshotMaxExchangeRate +\\n (snapshotMaxExchangeRate * growthRatePerSecond * timeElapsed) /\\n 1e18;\\n return maxExchangeRate;\\n }\\n\\n /**\\n * @notice Gets the underlying amount for correlated token\\n * @return underlyingAmount Amount of underlying token\\n */\\n function getUnderlyingAmount() public view virtual returns (uint256);\\n\\n /**\\n * @notice Fetches price of the token based on an underlying exchange rate\\n * @param exchangeRate The underlying exchange rate to use\\n * @return price The price of the token in scaled decimal places\\n */\\n function _calculatePrice(uint256 exchangeRate) internal view returns (uint256) {\\n uint256 underlyingUSDPrice = RESILIENT_ORACLE.getPrice(UNDERLYING_TOKEN);\\n\\n IERC20Metadata token = IERC20Metadata(CORRELATED_TOKEN);\\n uint256 decimals = token.decimals();\\n\\n return (exchangeRate * underlyingUSDPrice) / (10 ** decimals);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n * @custom:error Unauthorized error is thrown if the call is not allowed\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = ACCESS_CONTROL_MANAGER.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x808b444fa4d1d440dc43de290f1eb59a64646ce9085028b286fa30346305872e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6101a0604052348015610010575f80fd5b5060405161155938038061155983398101604081905261002f916103a6565b6060810151608082015160a083015160e084015161010085015161012086015161014087015161016088015161018089015161006f6301e1338087610481565b5f81905515801561007f57505f85115b8061009357505f8054118015610093575084155b156100b1576040516353b7e64560e11b815260040160405180910390fd5b8315806100bc575082155b80156100c757505f85115b156100e55760405163b8a5589b60e01b815260040160405180910390fd5b6100ee896102eb565b6100f7886102eb565b610100876102eb565b610109826102eb565b6001600160a01b0398891660805296881660a05294871660c052600192909255600255600355506004919091551660e0528051610145906102eb565b6020810151610153906102eb565b60c08101516101679063ffffffff16610315565b80516001600160a01b03908116610140526020820151166101005260408101516001811115610198576101986104a0565b6101208160018111156101ad576101ad6104a0565b815250508060c0015163ffffffff166101608163ffffffff168152505060a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610208573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061022c91906104b4565b60ff166101805261010051610140516101605160405162439f4b60e91b81526001600160a01b03928316600482015263ffffffff90911660248201525f928392169063873e960090604401606060405180830381865afa158015610292573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102b691906104ea565b925050915081806102c5575080155b156102e357604051637616640160e01b815260040160405180910390fd5b505050610532565b6001600160a01b038116610312576040516342bcdf7f60e11b815260040160405180910390fd5b50565b805f036103125760405163273e150360e21b815260040160405180910390fd5b6040516101a081016001600160401b038111828210171561036457634e487b7160e01b5f52604160045260245ffd5b60405290565b80516001600160a01b0381168114610380575f80fd5b919050565b805160028110610380575f80fd5b805163ffffffff81168114610380575f80fd5b5f6101a082840312156103b7575f80fd5b6103bf610335565b6103c88361036a565b81526103d66020840161036a565b60208201526103e760408401610385565b60408201526103f86060840161036a565b60608201526104096080840161036a565b608082015261041a60a0840161036a565b60a082015261042b60c08401610393565b60c082015260e0838101519082015261010080840151908201526101208084015190820152610140808401519082015261016061046981850161036a565b90820152610180928301519281019290925250919050565b5f8261049b57634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52602160045260245ffd5b5f602082840312156104c4575f80fd5b815160ff811681146104d4575f80fd5b9392505050565b80518015158114610380575f80fd5b5f805f606084860312156104fc575f80fd5b610505846104db565b9250602084015161ffff8116811461051b575f80fd5b9150610529604085016104db565b90509250925092565b60805160a05160c05160e0516101005161012051610140516101605161018051610f596106005f395f81816101d9015261099d01525f81816103070152818161081b01526108f601525f818161038b015281816107f301526108ce01525f818161014601526107a701525f81816102e001528181610847015261092201525f818161022e0152610b9a01525f818161034c0152818161069c0152610a6d01525f818161019a015281816106740152610a4101525f81816102a6015281816103b00152610adb0152610f595ff3fe608060405234801561000f575f80fd5b506004361061013d575f3560e01c806369240426116100b45780639c43eb54116100795780639c43eb541461033e578063a4edcd4c14610347578063abb856131461036e578063ac5a693e14610376578063bdf13af21461037e578063f46f16c214610386575f80fd5b8063692404261461029957806369818a35146102a15780637fc4e4a0146102c8578063809d7b31146102db578063879ac8f814610302575f80fd5b806341976e091161010557806341976e091461021657806345be2dc7146102295780635213f9c814610250578063596efe6f14610265578063643d813d1461026e578063671528d414610281575f80fd5b806302125d091461014157806307d0413c1461017e57806329db1be6146101955780633dae7c22146101d45780634169d2451461020d575b5f80fd5b6101687f000000000000000000000000000000000000000000000000000000000000000081565b6040516101759190610c57565b60405180910390f35b61018760015481565b604051908152602001610175565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610175565b6101fb7f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff9091168152602001610175565b61018760045481565b610187610224366004610c7d565b6103ad565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b61026361025e366004610ca3565b61045e565b005b61018760025481565b61026361027c366004610cba565b6104cf565b6102896105a5565b6040519015158152602001610175565b6102636105e0565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6102636102d6366004610cba565b610729565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610175565b61018760035481565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6101876107a1565b6101875f5481565b6101876109dd565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161461040057604051630f58058360e11b815260040160405180910390fd5b5f6104096107a1565b90506001545f036104245761041d81610a2a565b9392505050565b5f61042d6109dd565b90505f818311801561043e57508115155b610448578261044a565b815b905061045581610a2a565b95945050505050565b61049c6040518060400160405280601781526020017f736574536e617073686f744761702875696e7432353629000000000000000000815250610b81565b6004546040518291907feb3716d3f8388c182853c1dc98b18931f3a600bbab31f2ff48631f6412e4997f905f90a3600455565b61050d6040518060400160405280601e81526020017f73657447726f777468526174652875696e743235362c75696e74323536290000815250610b81565b5f5461051d6301e1338084610cee565b5f81905515801561052d57505f82115b8061054157505f8054118015610541575081155b1561055f576040516353b7e64560e11b815260040160405180910390fd5b6001545f54827fa65cbeb0e28a8803a912daac67c472c160aa01e2c988755fa424f290321de6088560405161059691815260200190565b60405180910390a45060015550565b5f6001545f036105b457505f90565b5f6105bd6109dd565b9050805f036105cd575f91505090565b5f6105d66107a1565b9190911192915050565b6001546003546105f09042610d0d565b10806105fc5750600154155b1561060357565b5f61060c6107a1565b90505f6106176109dd565b9050600454818311610629578261062b565b815b6106359190610d26565b6002819055426003555f0361065d57604051635f18388760e01b815260040160405180910390fd5b60405163b62cad6960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063b62cad69906024015f604051808303815f87803b1580156106dd575f80fd5b505af11580156106ef573d5f803e3d5ffd5b505050506003546002547f2c8c8fcb8c77a0ca21dcc3ab8fc0ade761557e76b1240cb40ebbef9fcee00f7d60405160405180910390a35050565b6107676040518060400160405280601c81526020017f736574536e617073686f742875696e743235362c75696e743235362900000000815250610b81565b60028290556003819055604051819083907f2c8c8fcb8c77a0ca21dcc3ab8fc0ade761557e76b1240cb40ebbef9fcee00f7d905f90a35050565b5f8060017f000000000000000000000000000000000000000000000000000000000000000060018111156107d7576107d7610c43565b036108b75760405163a31426d160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f000000000000000000000000000000000000000000000000000000000000000063ffffffff1660248301527f0000000000000000000000000000000000000000000000000000000000000000169063a31426d190604401602060405180830381865afa15801561088c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b09190610d39565b905061098e565b60405163abca0eab60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f000000000000000000000000000000000000000000000000000000000000000063ffffffff1660248301527f0000000000000000000000000000000000000000000000000000000000000000169063abca0eab90604401602060405180830381865afa158015610967573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061098b9190610d39565b90505b670de0b6b3a7640000816109c37f0000000000000000000000000000000000000000000000000000000000000000600a610e30565b6109cd9190610e3e565b6109d79190610cee565b91505090565b5f80600354426109ed9190610d0d565b90505f670de0b6b3a7640000825f54600254610a099190610e3e565b610a139190610e3e565b610a1d9190610cee565b60025461041d9190610d26565b6040516341976e0960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f9182917f000000000000000000000000000000000000000000000000000000000000000016906341976e0990602401602060405180830381865afa158015610ab2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ad69190610d39565b90505f7f000000000000000000000000000000000000000000000000000000000000000090505f816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b39573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b5d9190610e55565b60ff169050610b6d81600a610e75565b610b778487610e3e565b6104559190610cee565b6040516318c5e8ab60e01b81525f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906318c5e8ab90610bd19033908690600401610eae565b602060405180830381865afa158015610bec573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c109190610ed9565b905080610c3f57333083604051634a3fa29360e01b8152600401610c3693929190610ef8565b60405180910390fd5b5050565b634e487b7160e01b5f52602160045260245ffd5b6020810160028310610c7757634e487b7160e01b5f52602160045260245ffd5b91905290565b5f60208284031215610c8d575f80fd5b81356001600160a01b038116811461041d575f80fd5b5f60208284031215610cb3575f80fd5b5035919050565b5f8060408385031215610ccb575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52601160045260245ffd5b5f82610d0857634e487b7160e01b5f52601260045260245ffd5b500490565b81810381811115610d2057610d20610cda565b92915050565b80820180821115610d2057610d20610cda565b5f60208284031215610d49575f80fd5b5051919050565b600181815b80851115610d8a57815f1904821115610d7057610d70610cda565b80851615610d7d57918102915b93841c9390800290610d55565b509250929050565b5f82610da057506001610d20565b81610dac57505f610d20565b8160018114610dc25760028114610dcc57610de8565b6001915050610d20565b60ff841115610ddd57610ddd610cda565b50506001821b610d20565b5060208310610133831016604e8410600b8410161715610e0b575081810a610d20565b610e158383610d50565b805f1904821115610e2857610e28610cda565b029392505050565b5f61041d60ff841683610d92565b8082028115828204841417610d2057610d20610cda565b5f60208284031215610e65575f80fd5b815160ff8116811461041d575f80fd5b5f61041d8383610d92565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f90610ed190830184610e80565b949350505050565b5f60208284031215610ee9575f80fd5b8151801515811461041d575f80fd5b6001600160a01b038481168252831660208201526060604082018190525f9061045590830184610e8056fea2646970667358221220dd4434cf5ec982b81a2a3a25f96ea3d5d76d95704500f208da19253bd6abc73b64736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061013d575f3560e01c806369240426116100b45780639c43eb54116100795780639c43eb541461033e578063a4edcd4c14610347578063abb856131461036e578063ac5a693e14610376578063bdf13af21461037e578063f46f16c214610386575f80fd5b8063692404261461029957806369818a35146102a15780637fc4e4a0146102c8578063809d7b31146102db578063879ac8f814610302575f80fd5b806341976e091161010557806341976e091461021657806345be2dc7146102295780635213f9c814610250578063596efe6f14610265578063643d813d1461026e578063671528d414610281575f80fd5b806302125d091461014157806307d0413c1461017e57806329db1be6146101955780633dae7c22146101d45780634169d2451461020d575b5f80fd5b6101687f000000000000000000000000000000000000000000000000000000000000000081565b6040516101759190610c57565b60405180910390f35b61018760015481565b604051908152602001610175565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610175565b6101fb7f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff9091168152602001610175565b61018760045481565b610187610224366004610c7d565b6103ad565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b61026361025e366004610ca3565b61045e565b005b61018760025481565b61026361027c366004610cba565b6104cf565b6102896105a5565b6040519015158152602001610175565b6102636105e0565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6102636102d6366004610cba565b610729565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610175565b61018760035481565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6101876107a1565b6101875f5481565b6101876109dd565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161461040057604051630f58058360e11b815260040160405180910390fd5b5f6104096107a1565b90506001545f036104245761041d81610a2a565b9392505050565b5f61042d6109dd565b90505f818311801561043e57508115155b610448578261044a565b815b905061045581610a2a565b95945050505050565b61049c6040518060400160405280601781526020017f736574536e617073686f744761702875696e7432353629000000000000000000815250610b81565b6004546040518291907feb3716d3f8388c182853c1dc98b18931f3a600bbab31f2ff48631f6412e4997f905f90a3600455565b61050d6040518060400160405280601e81526020017f73657447726f777468526174652875696e743235362c75696e74323536290000815250610b81565b5f5461051d6301e1338084610cee565b5f81905515801561052d57505f82115b8061054157505f8054118015610541575081155b1561055f576040516353b7e64560e11b815260040160405180910390fd5b6001545f54827fa65cbeb0e28a8803a912daac67c472c160aa01e2c988755fa424f290321de6088560405161059691815260200190565b60405180910390a45060015550565b5f6001545f036105b457505f90565b5f6105bd6109dd565b9050805f036105cd575f91505090565b5f6105d66107a1565b9190911192915050565b6001546003546105f09042610d0d565b10806105fc5750600154155b1561060357565b5f61060c6107a1565b90505f6106176109dd565b9050600454818311610629578261062b565b815b6106359190610d26565b6002819055426003555f0361065d57604051635f18388760e01b815260040160405180910390fd5b60405163b62cad6960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063b62cad69906024015f604051808303815f87803b1580156106dd575f80fd5b505af11580156106ef573d5f803e3d5ffd5b505050506003546002547f2c8c8fcb8c77a0ca21dcc3ab8fc0ade761557e76b1240cb40ebbef9fcee00f7d60405160405180910390a35050565b6107676040518060400160405280601c81526020017f736574536e617073686f742875696e743235362c75696e743235362900000000815250610b81565b60028290556003819055604051819083907f2c8c8fcb8c77a0ca21dcc3ab8fc0ade761557e76b1240cb40ebbef9fcee00f7d905f90a35050565b5f8060017f000000000000000000000000000000000000000000000000000000000000000060018111156107d7576107d7610c43565b036108b75760405163a31426d160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f000000000000000000000000000000000000000000000000000000000000000063ffffffff1660248301527f0000000000000000000000000000000000000000000000000000000000000000169063a31426d190604401602060405180830381865afa15801561088c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b09190610d39565b905061098e565b60405163abca0eab60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f000000000000000000000000000000000000000000000000000000000000000063ffffffff1660248301527f0000000000000000000000000000000000000000000000000000000000000000169063abca0eab90604401602060405180830381865afa158015610967573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061098b9190610d39565b90505b670de0b6b3a7640000816109c37f0000000000000000000000000000000000000000000000000000000000000000600a610e30565b6109cd9190610e3e565b6109d79190610cee565b91505090565b5f80600354426109ed9190610d0d565b90505f670de0b6b3a7640000825f54600254610a099190610e3e565b610a139190610e3e565b610a1d9190610cee565b60025461041d9190610d26565b6040516341976e0960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f9182917f000000000000000000000000000000000000000000000000000000000000000016906341976e0990602401602060405180830381865afa158015610ab2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ad69190610d39565b90505f7f000000000000000000000000000000000000000000000000000000000000000090505f816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b39573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b5d9190610e55565b60ff169050610b6d81600a610e75565b610b778487610e3e565b6104559190610cee565b6040516318c5e8ab60e01b81525f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906318c5e8ab90610bd19033908690600401610eae565b602060405180830381865afa158015610bec573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c109190610ed9565b905080610c3f57333083604051634a3fa29360e01b8152600401610c3693929190610ef8565b60405180910390fd5b5050565b634e487b7160e01b5f52602160045260245ffd5b6020810160028310610c7757634e487b7160e01b5f52602160045260245ffd5b91905290565b5f60208284031215610c8d575f80fd5b81356001600160a01b038116811461041d575f80fd5b5f60208284031215610cb3575f80fd5b5035919050565b5f8060408385031215610ccb575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52601160045260245ffd5b5f82610d0857634e487b7160e01b5f52601260045260245ffd5b500490565b81810381811115610d2057610d20610cda565b92915050565b80820180821115610d2057610d20610cda565b5f60208284031215610d49575f80fd5b5051919050565b600181815b80851115610d8a57815f1904821115610d7057610d70610cda565b80851615610d7d57918102915b93841c9390800290610d55565b509250929050565b5f82610da057506001610d20565b81610dac57505f610d20565b8160018114610dc25760028114610dcc57610de8565b6001915050610d20565b60ff841115610ddd57610ddd610cda565b50506001821b610d20565b5060208310610133831016604e8410600b8410161715610e0b575081810a610d20565b610e158383610d50565b805f1904821115610e2857610e28610cda565b029392505050565b5f61041d60ff841683610d92565b8082028115828204841417610d2057610d20610cda565b5f60208284031215610e65575f80fd5b815160ff8116811461041d575f80fd5b5f61041d8383610d92565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f90610ed190830184610e80565b949350505050565b5f60208284031215610ee9575f80fd5b8151801515811461041d575f80fd5b6001600160a01b038481168252831660208201526060604082018190525f9061045590830184610e8056fea2646970667358221220dd4434cf5ec982b81a2a3a25f96ea3d5d76d95704500f208da19253bd6abc73b64736f6c63430008190033", + "devdoc": { + "author": "Venus", + "details": "As a base price the oracle uses either the price of the Pendle market's asset (in this case PT_TO_ASSET rate should be used) or the price of the Pendle market's interest bearing token (e.g. wstETH for stETH; in this case PT_TO_SY rate should be used). Technically, interest bearing token is different from standardized yield (SY) token, but since SY is a wrapper around an interest bearing token, we can safely assume the prices of the two are equal. This is not always true for asset price though: using PT_TO_ASSET rate assumes that the yield token can be seamlessly redeemed for the underlying asset. In reality, this might not always be the case. For more details, see https://docs.pendle.finance/Developers/Contracts/StandardizedYield", + "kind": "dev", + "methods": { + "constructor": { + "custom:error": "InvalidDuration Thrown if the duration is invalid" + }, + "getMaxAllowedExchangeRate()": { + "returns": { + "_0": "maxExchangeRate Maximum allowed exchange rate" + } + }, + "getPrice(address)": { + "custom:error": "InvalidTokenAddress error is thrown if the token address is invalid", + "params": { + "asset": "Address of the token" + }, + "returns": { + "_0": "price The price of the token in scaled decimal places. It can be capped to a maximum value taking into account the growth rate" + } + }, + "getUnderlyingAmount()": { + "returns": { + "_0": "amount The amount of underlying token (either the market's asset or the yield token) for 1 PT, adjusted for decimals such that the result has the same precision as the underlying token" + } + }, + "isCapped()": { + "returns": { + "_0": "isCapped Boolean indicating if the price is capped" + } + }, + "setGrowthRate(uint256,uint256)": { + "custom:error": "InvalidGrowthRate error is thrown if the growth rate is invalid", + "custom:event": "Emits GrowthRateUpdated event on successful update of the growth rate", + "params": { + "_annualGrowthRate": "The annual growth rate to set", + "_snapshotInterval": "The snapshot interval to set" + } + }, + "setSnapshot(uint256,uint256)": { + "custom:event": "Emits SnapshotUpdated event on successful update of the snapshot", + "params": { + "_snapshotMaxExchangeRate": "The exchange rate to set", + "_snapshotTimestamp": "The timestamp to set" + } + }, + "setSnapshotGap(uint256)": { + "custom:event": "Emits SnapshotGapUpdated event on successful update of the snapshot gap", + "params": { + "_snapshotGap": "The snapshot gap to set" + } + }, + "updateSnapshot()": { + "custom:error": "InvalidSnapshotMaxExchangeRate error is thrown if the max snapshot exchange rate is zero", + "custom:event": "Emits SnapshotUpdated event on successful update of the snapshot" + } + }, + "stateVariables": { + "UNDERLYING_DECIMALS": { + "details": "We make an assumption that the underlying decimals will not change throughout the lifetime of the Pendle market" + } + }, + "title": "PendleOracle", + "version": 1 + }, + "userdoc": { + "errors": { + "InvalidDuration()": [ + { + "notice": "Thrown if the duration is invalid" + } + ], + "InvalidGrowthRate()": [ + { + "notice": "Thrown if the growth rate is invalid" + } + ], + "InvalidInitialSnapshot()": [ + { + "notice": "Thrown if the initial snapshot is invalid" + } + ], + "InvalidSnapshotMaxExchangeRate()": [ + { + "notice": "Thrown if the max snapshot exchange rate is invalid" + } + ], + "InvalidTokenAddress()": [ + { + "notice": "Thrown if the token address is invalid" + } + ], + "Unauthorized(address,address,string)": [ + { + "notice": "@notice Thrown when the action is prohibited by AccessControlManager" + } + ], + "ZeroAddressNotAllowed()": [ + { + "notice": "Thrown if the supplied address is a zero address where it is not allowed" + } + ], + "ZeroValueNotAllowed()": [ + { + "notice": "Thrown if the supplied value is 0 where it is not allowed" + } + ] + }, + "events": { + "GrowthRateUpdated(uint256,uint256,uint256,uint256)": { + "notice": "Emitted when the growth rate is updated" + }, + "SnapshotGapUpdated(uint256,uint256)": { + "notice": "Emitted when the snapshot gap is updated" + }, + "SnapshotUpdated(uint256,uint256)": { + "notice": "Emitted when the snapshot is updated" + } + }, + "kind": "user", + "methods": { + "ACCESS_CONTROL_MANAGER()": { + "notice": "Address of the AccessControlManager contract" + }, + "CORRELATED_TOKEN()": { + "notice": "Address of the correlated token" + }, + "MARKET()": { + "notice": "Address of the market" + }, + "PT_ORACLE()": { + "notice": "Address of the PT oracle" + }, + "RATE_KIND()": { + "notice": "Whether to use PT/SY (standardized yield token) rate or PT/market asset rate" + }, + "RESILIENT_ORACLE()": { + "notice": "Address of Resilient Oracle" + }, + "TWAP_DURATION()": { + "notice": "Twap duration for the oracle" + }, + "UNDERLYING_DECIMALS()": { + "notice": "Decimals of the underlying token" + }, + "UNDERLYING_TOKEN()": { + "notice": "Address of the underlying token" + }, + "constructor": { + "notice": "Constructor for the implementation contract." + }, + "getMaxAllowedExchangeRate()": { + "notice": "Gets the maximum allowed exchange rate for token" + }, + "getPrice(address)": { + "notice": "Fetches the price of the token" + }, + "getUnderlyingAmount()": { + "notice": "Fetches the amount of underlying token for 1 PT" + }, + "isCapped()": { + "notice": "Returns if the price is capped" + }, + "setGrowthRate(uint256,uint256)": { + "notice": "Sets the growth rate and snapshot interval" + }, + "setSnapshot(uint256,uint256)": { + "notice": "Directly sets the snapshot exchange rate and timestamp" + }, + "setSnapshotGap(uint256)": { + "notice": "Sets the snapshot gap" + }, + "snapshotGap()": { + "notice": "Gap to add when updating the snapshot" + }, + "snapshotInterval()": { + "notice": "Snapshot update interval" + }, + "snapshotMaxExchangeRate()": { + "notice": "Last stored snapshot maximum exchange rate" + }, + "snapshotTimestamp()": { + "notice": "Last stored snapshot timestamp" + }, + "updateSnapshot()": { + "notice": "Updates the snapshot price and timestamp" + } + }, + "notice": "This oracle fetches the price of a pendle token", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 6602, + "contract": "contracts/oracles/PendleOracle.sol:PendleOracle", + "label": "growthRatePerSecond", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 6605, + "contract": "contracts/oracles/PendleOracle.sol:PendleOracle", + "label": "snapshotInterval", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 6608, + "contract": "contracts/oracles/PendleOracle.sol:PendleOracle", + "label": "snapshotMaxExchangeRate", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 6611, + "contract": "contracts/oracles/PendleOracle.sol:PendleOracle", + "label": "snapshotTimestamp", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 6614, + "contract": "contracts/oracles/PendleOracle.sol:PendleOracle", + "label": "snapshotGap", + "offset": 0, + "slot": "4", + "type": "t_uint256" + } + ], + "types": { + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/bscmainnet/PendleOracle-PT-clisBNB-25JUN2026_Reference_PtToAsset.json b/deployments/bscmainnet/PendleOracle-PT-clisBNB-25JUN2026_Reference_PtToAsset.json new file mode 100644 index 00000000..244a52da --- /dev/null +++ b/deployments/bscmainnet/PendleOracle-PT-clisBNB-25JUN2026_Reference_PtToAsset.json @@ -0,0 +1,785 @@ +{ + "address": "0xc94866f155FEA46C398385665B08B813D20DF802", + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "address", + "name": "ptOracle", + "type": "address" + }, + { + "internalType": "enum PendleOracle.RateKind", + "name": "rateKind", + "type": "uint8" + }, + { + "internalType": "address", + "name": "ptToken", + "type": "address" + }, + { + "internalType": "address", + "name": "underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "resilientOracle", + "type": "address" + }, + { + "internalType": "uint32", + "name": "twapDuration", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "annualGrowthRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "snapshotInterval", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSnapshotMaxExchangeRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSnapshotTimestamp", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager", + "type": "address" + }, + { + "internalType": "uint256", + "name": "snapshotGap", + "type": "uint256" + } + ], + "internalType": "struct PendleOracle.ConstructorParams", + "name": "params", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidDuration", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidGrowthRate", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialSnapshot", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSnapshotMaxExchangeRate", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTokenAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValueNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldGrowthRatePerSecond", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newGrowthRatePerSecond", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "oldSnapshotInterval", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSnapshotInterval", + "type": "uint256" + } + ], + "name": "GrowthRateUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldSnapshotGap", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newSnapshotGap", + "type": "uint256" + } + ], + "name": "SnapshotGapUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "maxExchangeRate", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "SnapshotUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "ACCESS_CONTROL_MANAGER", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CORRELATED_TOKEN", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MARKET", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PT_ORACLE", + "outputs": [ + { + "internalType": "contract IPendlePtOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RATE_KIND", + "outputs": [ + { + "internalType": "enum PendleOracle.RateKind", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESILIENT_ORACLE", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TWAP_DURATION", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNDERLYING_DECIMALS", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNDERLYING_TOKEN", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxAllowedExchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUnderlyingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "growthRatePerSecond", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isCapped", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_annualGrowthRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_snapshotInterval", + "type": "uint256" + } + ], + "name": "setGrowthRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_snapshotMaxExchangeRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_snapshotTimestamp", + "type": "uint256" + } + ], + "name": "setSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_snapshotGap", + "type": "uint256" + } + ], + "name": "setSnapshotGap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotGap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotInterval", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotMaxExchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "updateSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x675520aa7ebe28dd4d079220c696c83b70c638db64e35d068c7f826b285d59bc", + "receipt": { + "to": null, + "from": "0x24c30C9C84b8a3C71A521ad30007ED47372331b3", + "contractAddress": "0xc94866f155FEA46C398385665B08B813D20DF802", + "transactionIndex": 97, + "gasUsed": "969829", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc10e4e23476504ca0cbd5775eeb8d187f519fa32b32c82f63866be60bedc0de4", + "transactionHash": "0x675520aa7ebe28dd4d079220c696c83b70c638db64e35d068c7f826b285d59bc", + "logs": [], + "blockNumber": 74954032, + "cumulativeGasUsed": "17395137", + "status": 1, + "byzantium": true + }, + "args": [ + { + "market": "0x3C1a3D6B69A866444Fe506F7D38a00a1C2D859C5", + "ptOracle": "0x9a9fa8338dd5e5b2188006f1cd2ef26d921650c2", + "rateKind": 0, + "ptToken": "0xe052823b4aefc6e230FAf46231A57d0905E30AE0", + "underlyingToken": "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B", + "resilientOracle": "0x6592b5DE802159F3E74B2486b091D11a8256ab8A", + "twapDuration": 1800, + "annualGrowthRate": 0, + "snapshotInterval": 0, + "initialSnapshotMaxExchangeRate": 0, + "initialSnapshotTimestamp": 0, + "accessControlManager": "0x4788629abc6cfca10f9f969efdeaa1cf70c23555", + "snapshotGap": 0 + } + ], + "numDeployments": 1, + "solcInputHash": "a5bca20982c9bb49cb2eb7474644c181", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"ptOracle\",\"type\":\"address\"},{\"internalType\":\"enum PendleOracle.RateKind\",\"name\":\"rateKind\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"ptToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"underlyingToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resilientOracle\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"twapDuration\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"annualGrowthRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"snapshotInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"initialSnapshotMaxExchangeRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"initialSnapshotTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"accessControlManager\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"snapshotGap\",\"type\":\"uint256\"}],\"internalType\":\"struct PendleOracle.ConstructorParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidDuration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidGrowthRate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialSnapshot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSnapshotMaxExchangeRate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldGrowthRatePerSecond\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newGrowthRatePerSecond\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldSnapshotInterval\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSnapshotInterval\",\"type\":\"uint256\"}],\"name\":\"GrowthRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldSnapshotGap\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newSnapshotGap\",\"type\":\"uint256\"}],\"name\":\"SnapshotGapUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"maxExchangeRate\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"SnapshotUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ACCESS_CONTROL_MANAGER\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"CORRELATED_TOKEN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MARKET\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PT_ORACLE\",\"outputs\":[{\"internalType\":\"contract IPendlePtOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RATE_KIND\",\"outputs\":[{\"internalType\":\"enum PendleOracle.RateKind\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RESILIENT_ORACLE\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TWAP_DURATION\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UNDERLYING_DECIMALS\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UNDERLYING_TOKEN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getMaxAllowedExchangeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getUnderlyingAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"growthRatePerSecond\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isCapped\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_annualGrowthRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_snapshotInterval\",\"type\":\"uint256\"}],\"name\":\"setGrowthRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_snapshotMaxExchangeRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_snapshotTimestamp\",\"type\":\"uint256\"}],\"name\":\"setSnapshot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_snapshotGap\",\"type\":\"uint256\"}],\"name\":\"setSnapshotGap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"snapshotGap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"snapshotInterval\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"snapshotMaxExchangeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"snapshotTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateSnapshot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"As a base price the oracle uses either the price of the Pendle market's asset (in this case PT_TO_ASSET rate should be used) or the price of the Pendle market's interest bearing token (e.g. wstETH for stETH; in this case PT_TO_SY rate should be used). Technically, interest bearing token is different from standardized yield (SY) token, but since SY is a wrapper around an interest bearing token, we can safely assume the prices of the two are equal. This is not always true for asset price though: using PT_TO_ASSET rate assumes that the yield token can be seamlessly redeemed for the underlying asset. In reality, this might not always be the case. For more details, see https://docs.pendle.finance/Developers/Contracts/StandardizedYield\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:error\":\"InvalidDuration Thrown if the duration is invalid\"},\"getMaxAllowedExchangeRate()\":{\"returns\":{\"_0\":\"maxExchangeRate Maximum allowed exchange rate\"}},\"getPrice(address)\":{\"custom:error\":\"InvalidTokenAddress error is thrown if the token address is invalid\",\"params\":{\"asset\":\"Address of the token\"},\"returns\":{\"_0\":\"price The price of the token in scaled decimal places. It can be capped to a maximum value taking into account the growth rate\"}},\"getUnderlyingAmount()\":{\"returns\":{\"_0\":\"amount The amount of underlying token (either the market's asset or the yield token) for 1 PT, adjusted for decimals such that the result has the same precision as the underlying token\"}},\"isCapped()\":{\"returns\":{\"_0\":\"isCapped Boolean indicating if the price is capped\"}},\"setGrowthRate(uint256,uint256)\":{\"custom:error\":\"InvalidGrowthRate error is thrown if the growth rate is invalid\",\"custom:event\":\"Emits GrowthRateUpdated event on successful update of the growth rate\",\"params\":{\"_annualGrowthRate\":\"The annual growth rate to set\",\"_snapshotInterval\":\"The snapshot interval to set\"}},\"setSnapshot(uint256,uint256)\":{\"custom:event\":\"Emits SnapshotUpdated event on successful update of the snapshot\",\"params\":{\"_snapshotMaxExchangeRate\":\"The exchange rate to set\",\"_snapshotTimestamp\":\"The timestamp to set\"}},\"setSnapshotGap(uint256)\":{\"custom:event\":\"Emits SnapshotGapUpdated event on successful update of the snapshot gap\",\"params\":{\"_snapshotGap\":\"The snapshot gap to set\"}},\"updateSnapshot()\":{\"custom:error\":\"InvalidSnapshotMaxExchangeRate error is thrown if the max snapshot exchange rate is zero\",\"custom:event\":\"Emits SnapshotUpdated event on successful update of the snapshot\"}},\"stateVariables\":{\"UNDERLYING_DECIMALS\":{\"details\":\"We make an assumption that the underlying decimals will not change throughout the lifetime of the Pendle market\"}},\"title\":\"PendleOracle\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidDuration()\":[{\"notice\":\"Thrown if the duration is invalid\"}],\"InvalidGrowthRate()\":[{\"notice\":\"Thrown if the growth rate is invalid\"}],\"InvalidInitialSnapshot()\":[{\"notice\":\"Thrown if the initial snapshot is invalid\"}],\"InvalidSnapshotMaxExchangeRate()\":[{\"notice\":\"Thrown if the max snapshot exchange rate is invalid\"}],\"InvalidTokenAddress()\":[{\"notice\":\"Thrown if the token address is invalid\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"@notice Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"GrowthRateUpdated(uint256,uint256,uint256,uint256)\":{\"notice\":\"Emitted when the growth rate is updated\"},\"SnapshotGapUpdated(uint256,uint256)\":{\"notice\":\"Emitted when the snapshot gap is updated\"},\"SnapshotUpdated(uint256,uint256)\":{\"notice\":\"Emitted when the snapshot is updated\"}},\"kind\":\"user\",\"methods\":{\"ACCESS_CONTROL_MANAGER()\":{\"notice\":\"Address of the AccessControlManager contract\"},\"CORRELATED_TOKEN()\":{\"notice\":\"Address of the correlated token\"},\"MARKET()\":{\"notice\":\"Address of the market\"},\"PT_ORACLE()\":{\"notice\":\"Address of the PT oracle\"},\"RATE_KIND()\":{\"notice\":\"Whether to use PT/SY (standardized yield token) rate or PT/market asset rate\"},\"RESILIENT_ORACLE()\":{\"notice\":\"Address of Resilient Oracle\"},\"TWAP_DURATION()\":{\"notice\":\"Twap duration for the oracle\"},\"UNDERLYING_DECIMALS()\":{\"notice\":\"Decimals of the underlying token\"},\"UNDERLYING_TOKEN()\":{\"notice\":\"Address of the underlying token\"},\"constructor\":{\"notice\":\"Constructor for the implementation contract.\"},\"getMaxAllowedExchangeRate()\":{\"notice\":\"Gets the maximum allowed exchange rate for token\"},\"getPrice(address)\":{\"notice\":\"Fetches the price of the token\"},\"getUnderlyingAmount()\":{\"notice\":\"Fetches the amount of underlying token for 1 PT\"},\"isCapped()\":{\"notice\":\"Returns if the price is capped\"},\"setGrowthRate(uint256,uint256)\":{\"notice\":\"Sets the growth rate and snapshot interval\"},\"setSnapshot(uint256,uint256)\":{\"notice\":\"Directly sets the snapshot exchange rate and timestamp\"},\"setSnapshotGap(uint256)\":{\"notice\":\"Sets the snapshot gap\"},\"snapshotGap()\":{\"notice\":\"Gap to add when updating the snapshot\"},\"snapshotInterval()\":{\"notice\":\"Snapshot update interval\"},\"snapshotMaxExchangeRate()\":{\"notice\":\"Last stored snapshot maximum exchange rate\"},\"snapshotTimestamp()\":{\"notice\":\"Last stored snapshot timestamp\"},\"updateSnapshot()\":{\"notice\":\"Updates the snapshot price and timestamp\"}},\"notice\":\"This oracle fetches the price of a pendle token\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/oracles/PendleOracle.sol\":\"PendleOracle\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xdb88e14d50dd21889ca3329d755673d022c47e8da005b6a545c7f69c2c4b7b86\",\"license\":\"BSD-3-Clause\"},\"contracts/interfaces/ICappedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface ICappedOracle {\\n function updateSnapshot() external;\\n}\\n\",\"keccak256\":\"0xad239e65b5e92b3486418c5ccca120247702251f9724cd96657c3cfdc7fedc31\",\"license\":\"BSD-3-Clause\"},\"contracts/interfaces/IPendlePtOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IPendlePtOracle {\\n function getPtToAssetRate(address market, uint32 duration) external view returns (uint256);\\n\\n function getPtToSyRate(address market, uint32 duration) external view returns (uint256);\\n\\n function getOracleState(\\n address market,\\n uint32 duration\\n )\\n external\\n view\\n returns (bool increaseCardinalityRequired, uint16 cardinalityRequired, bool oldestObservationSatisfied);\\n}\\n\",\"keccak256\":\"0x14d96d7f75397e4291288ef6367053bd970d95fc0c3e2a028b077f6342e0160a\",\"license\":\"BSD-3-Clause\"},\"contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"contracts/oracles/PendleOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IPendlePtOracle } from \\\"../interfaces/IPendlePtOracle.sol\\\";\\nimport { CorrelatedTokenOracle } from \\\"./common/CorrelatedTokenOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\n/**\\n * @title PendleOracle\\n * @author Venus\\n * @notice This oracle fetches the price of a pendle token\\n * @dev As a base price the oracle uses either the price of the Pendle\\n * market's asset (in this case PT_TO_ASSET rate should be used) or\\n * the price of the Pendle market's interest bearing token (e.g. wstETH\\n * for stETH; in this case PT_TO_SY rate should be used). Technically,\\n * interest bearing token is different from standardized yield (SY) token,\\n * but since SY is a wrapper around an interest bearing token, we can safely\\n * assume the prices of the two are equal. This is not always true for asset\\n * price though: using PT_TO_ASSET rate assumes that the yield token can\\n * be seamlessly redeemed for the underlying asset. In reality, this might\\n * not always be the case. For more details, see\\n * https://docs.pendle.finance/Developers/Contracts/StandardizedYield\\n */\\ncontract PendleOracle is CorrelatedTokenOracle {\\n struct ConstructorParams {\\n /// @notice Pendle market\\n address market;\\n /// @notice Pendle oracle\\n address ptOracle;\\n /// @notice Either PT_TO_ASSET or PT_TO_SY\\n RateKind rateKind;\\n /// @notice Pendle PT token\\n address ptToken;\\n /// @notice Underlying token, can be either the market's asset or the interest bearing token\\n address underlyingToken;\\n /// @notice Resilient oracle to get the underlying token price from\\n address resilientOracle;\\n /// @notice TWAP duration to call Pendle oracle with\\n uint32 twapDuration;\\n /// @notice Annual growth rate of the underlying token\\n uint256 annualGrowthRate;\\n /// @notice Snapshot interval for the oracle\\n uint256 snapshotInterval;\\n /// @notice Initial exchange rate of the underlying token\\n uint256 initialSnapshotMaxExchangeRate;\\n /// @notice Initial timestamp of the underlying token\\n uint256 initialSnapshotTimestamp;\\n /// @notice Access control manager\\n address accessControlManager;\\n /// @notice Gap to add when updating the snapshot\\n uint256 snapshotGap;\\n }\\n\\n /// @notice Which asset to use as a base for the returned PT\\n /// price. Can be either a standardized yield token (SY), in\\n /// this case PT/SY price is returned, or the Pendle\\n /// market's asset directly.\\n enum RateKind {\\n PT_TO_ASSET,\\n PT_TO_SY\\n }\\n\\n /// @notice Address of the PT oracle\\n IPendlePtOracle public immutable PT_ORACLE;\\n\\n /// @notice Whether to use PT/SY (standardized yield token) rate\\n /// or PT/market asset rate\\n RateKind public immutable RATE_KIND;\\n\\n /// @notice Address of the market\\n address public immutable MARKET;\\n\\n /// @notice Twap duration for the oracle\\n uint32 public immutable TWAP_DURATION;\\n\\n /// @notice Decimals of the underlying token\\n /// @dev We make an assumption that the underlying decimals will\\n /// not change throughout the lifetime of the Pendle market\\n uint8 public immutable UNDERLYING_DECIMALS;\\n\\n /// @notice Thrown if the duration is invalid\\n error InvalidDuration();\\n\\n /**\\n * @notice Constructor for the implementation contract.\\n * @custom:error InvalidDuration Thrown if the duration is invalid\\n */\\n constructor(\\n ConstructorParams memory params\\n )\\n CorrelatedTokenOracle(\\n params.ptToken,\\n params.underlyingToken,\\n params.resilientOracle,\\n params.annualGrowthRate,\\n params.snapshotInterval,\\n params.initialSnapshotMaxExchangeRate,\\n params.initialSnapshotTimestamp,\\n params.accessControlManager,\\n params.snapshotGap\\n )\\n {\\n ensureNonzeroAddress(params.market);\\n ensureNonzeroAddress(params.ptOracle);\\n ensureNonzeroValue(params.twapDuration);\\n\\n MARKET = params.market;\\n PT_ORACLE = IPendlePtOracle(params.ptOracle);\\n RATE_KIND = params.rateKind;\\n TWAP_DURATION = params.twapDuration;\\n UNDERLYING_DECIMALS = IERC20Metadata(UNDERLYING_TOKEN).decimals();\\n\\n (bool increaseCardinalityRequired, , bool oldestObservationSatisfied) = PT_ORACLE.getOracleState(\\n MARKET,\\n TWAP_DURATION\\n );\\n if (increaseCardinalityRequired || !oldestObservationSatisfied) {\\n revert InvalidDuration();\\n }\\n }\\n\\n /// @notice Fetches the amount of underlying token for 1 PT\\n /// @return amount The amount of underlying token (either the market's asset\\n /// or the yield token) for 1 PT, adjusted for decimals such that the result\\n /// has the same precision as the underlying token\\n function getUnderlyingAmount() public view override returns (uint256) {\\n uint256 rate;\\n if (RATE_KIND == RateKind.PT_TO_SY) {\\n rate = PT_ORACLE.getPtToSyRate(MARKET, TWAP_DURATION);\\n } else {\\n rate = PT_ORACLE.getPtToAssetRate(MARKET, TWAP_DURATION);\\n }\\n return ((10 ** UNDERLYING_DECIMALS) * rate) / 1e18;\\n }\\n}\\n\",\"keccak256\":\"0xaa7963ac7657ea62079c2162cb4fc45524f8ffbbc6e84f89a5d4e54b71dc6025\",\"license\":\"BSD-3-Clause\"},\"contracts/oracles/common/CorrelatedTokenOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { OracleInterface, ResilientOracleInterface } from \\\"../../interfaces/OracleInterface.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { SECONDS_PER_YEAR } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { ICappedOracle } from \\\"../../interfaces/ICappedOracle.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title CorrelatedTokenOracle\\n * @notice This oracle fetches the price of a token that is correlated to another token.\\n */\\nabstract contract CorrelatedTokenOracle is OracleInterface, ICappedOracle {\\n /// @notice Address of the correlated token\\n address public immutable CORRELATED_TOKEN;\\n\\n /// @notice Address of the underlying token\\n address public immutable UNDERLYING_TOKEN;\\n\\n /// @notice Address of Resilient Oracle\\n ResilientOracleInterface public immutable RESILIENT_ORACLE;\\n\\n /// @notice Address of the AccessControlManager contract\\n IAccessControlManagerV8 public immutable ACCESS_CONTROL_MANAGER;\\n\\n //// @notice Growth rate percentage in seconds. Ex: 1e18 is 100%\\n uint256 public growthRatePerSecond;\\n\\n /// @notice Snapshot update interval\\n uint256 public snapshotInterval;\\n\\n /// @notice Last stored snapshot maximum exchange rate\\n uint256 public snapshotMaxExchangeRate;\\n\\n /// @notice Last stored snapshot timestamp\\n uint256 public snapshotTimestamp;\\n\\n /// @notice Gap to add when updating the snapshot\\n uint256 public snapshotGap;\\n\\n /// @notice Emitted when the snapshot is updated\\n event SnapshotUpdated(uint256 indexed maxExchangeRate, uint256 indexed timestamp);\\n\\n /// @notice Emitted when the growth rate is updated\\n event GrowthRateUpdated(\\n uint256 indexed oldGrowthRatePerSecond,\\n uint256 indexed newGrowthRatePerSecond,\\n uint256 indexed oldSnapshotInterval,\\n uint256 newSnapshotInterval\\n );\\n\\n /// @notice Emitted when the snapshot gap is updated\\n event SnapshotGapUpdated(uint256 indexed oldSnapshotGap, uint256 indexed newSnapshotGap);\\n\\n /// @notice Thrown if the token address is invalid\\n error InvalidTokenAddress();\\n\\n /// @notice Thrown if the growth rate is invalid\\n error InvalidGrowthRate();\\n\\n /// @notice Thrown if the initial snapshot is invalid\\n error InvalidInitialSnapshot();\\n\\n /// @notice Thrown if the max snapshot exchange rate is invalid\\n error InvalidSnapshotMaxExchangeRate();\\n\\n /// @notice @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n /**\\n * @notice Constructor for the implementation contract.\\n * @custom:error InvalidGrowthRate error is thrown if the growth rate is invalid\\n * @custom:error InvalidInitialSnapshot error is thrown if the initial snapshot values are invalid\\n */\\n constructor(\\n address _correlatedToken,\\n address _underlyingToken,\\n address _resilientOracle,\\n uint256 _annualGrowthRate,\\n uint256 _snapshotInterval,\\n uint256 _initialSnapshotMaxExchangeRate,\\n uint256 _initialSnapshotTimestamp,\\n address _accessControlManager,\\n uint256 _snapshotGap\\n ) {\\n growthRatePerSecond = _annualGrowthRate / SECONDS_PER_YEAR;\\n\\n if ((growthRatePerSecond == 0 && _snapshotInterval > 0) || (growthRatePerSecond > 0 && _snapshotInterval == 0))\\n revert InvalidGrowthRate();\\n\\n if ((_initialSnapshotMaxExchangeRate == 0 || _initialSnapshotTimestamp == 0) && _snapshotInterval > 0) {\\n revert InvalidInitialSnapshot();\\n }\\n\\n ensureNonzeroAddress(_correlatedToken);\\n ensureNonzeroAddress(_underlyingToken);\\n ensureNonzeroAddress(_resilientOracle);\\n ensureNonzeroAddress(_accessControlManager);\\n\\n CORRELATED_TOKEN = _correlatedToken;\\n UNDERLYING_TOKEN = _underlyingToken;\\n RESILIENT_ORACLE = ResilientOracleInterface(_resilientOracle);\\n snapshotInterval = _snapshotInterval;\\n\\n snapshotMaxExchangeRate = _initialSnapshotMaxExchangeRate;\\n snapshotTimestamp = _initialSnapshotTimestamp;\\n snapshotGap = _snapshotGap;\\n\\n ACCESS_CONTROL_MANAGER = IAccessControlManagerV8(_accessControlManager);\\n }\\n\\n /**\\n * @notice Directly sets the snapshot exchange rate and timestamp\\n * @param _snapshotMaxExchangeRate The exchange rate to set\\n * @param _snapshotTimestamp The timestamp to set\\n * @custom:event Emits SnapshotUpdated event on successful update of the snapshot\\n */\\n function setSnapshot(uint256 _snapshotMaxExchangeRate, uint256 _snapshotTimestamp) external {\\n _checkAccessAllowed(\\\"setSnapshot(uint256,uint256)\\\");\\n\\n snapshotMaxExchangeRate = _snapshotMaxExchangeRate;\\n snapshotTimestamp = _snapshotTimestamp;\\n\\n emit SnapshotUpdated(snapshotMaxExchangeRate, snapshotTimestamp);\\n }\\n\\n /**\\n * @notice Sets the growth rate and snapshot interval\\n * @param _annualGrowthRate The annual growth rate to set\\n * @param _snapshotInterval The snapshot interval to set\\n * @custom:error InvalidGrowthRate error is thrown if the growth rate is invalid\\n * @custom:event Emits GrowthRateUpdated event on successful update of the growth rate\\n */\\n function setGrowthRate(uint256 _annualGrowthRate, uint256 _snapshotInterval) external {\\n _checkAccessAllowed(\\\"setGrowthRate(uint256,uint256)\\\");\\n uint256 oldGrowthRatePerSecond = growthRatePerSecond;\\n\\n growthRatePerSecond = _annualGrowthRate / SECONDS_PER_YEAR;\\n\\n if ((growthRatePerSecond == 0 && _snapshotInterval > 0) || (growthRatePerSecond > 0 && _snapshotInterval == 0))\\n revert InvalidGrowthRate();\\n\\n emit GrowthRateUpdated(oldGrowthRatePerSecond, growthRatePerSecond, snapshotInterval, _snapshotInterval);\\n\\n snapshotInterval = _snapshotInterval;\\n }\\n\\n /**\\n * @notice Sets the snapshot gap\\n * @param _snapshotGap The snapshot gap to set\\n * @custom:event Emits SnapshotGapUpdated event on successful update of the snapshot gap\\n */\\n function setSnapshotGap(uint256 _snapshotGap) external {\\n _checkAccessAllowed(\\\"setSnapshotGap(uint256)\\\");\\n\\n emit SnapshotGapUpdated(snapshotGap, _snapshotGap);\\n\\n snapshotGap = _snapshotGap;\\n }\\n\\n /**\\n * @notice Returns if the price is capped\\n * @return isCapped Boolean indicating if the price is capped\\n */\\n function isCapped() external view virtual returns (bool) {\\n if (snapshotInterval == 0) {\\n return false;\\n }\\n\\n uint256 maxAllowedExchangeRate = getMaxAllowedExchangeRate();\\n if (maxAllowedExchangeRate == 0) {\\n return false;\\n }\\n\\n uint256 exchangeRate = getUnderlyingAmount();\\n\\n return exchangeRate > maxAllowedExchangeRate;\\n }\\n\\n /**\\n * @notice Updates the snapshot price and timestamp\\n * @custom:event Emits SnapshotUpdated event on successful update of the snapshot\\n * @custom:error InvalidSnapshotMaxExchangeRate error is thrown if the max snapshot exchange rate is zero\\n */\\n function updateSnapshot() public override {\\n if (block.timestamp - snapshotTimestamp < snapshotInterval || snapshotInterval == 0) return;\\n\\n uint256 exchangeRate = getUnderlyingAmount();\\n uint256 maxAllowedExchangeRate = getMaxAllowedExchangeRate();\\n\\n snapshotMaxExchangeRate =\\n (exchangeRate > maxAllowedExchangeRate ? maxAllowedExchangeRate : exchangeRate) +\\n snapshotGap;\\n snapshotTimestamp = block.timestamp;\\n\\n if (snapshotMaxExchangeRate == 0) revert InvalidSnapshotMaxExchangeRate();\\n\\n RESILIENT_ORACLE.updateAssetPrice(UNDERLYING_TOKEN);\\n emit SnapshotUpdated(snapshotMaxExchangeRate, snapshotTimestamp);\\n }\\n\\n /**\\n * @notice Fetches the price of the token\\n * @param asset Address of the token\\n * @return price The price of the token in scaled decimal places. It can be capped\\n * to a maximum value taking into account the growth rate\\n * @custom:error InvalidTokenAddress error is thrown if the token address is invalid\\n */\\n function getPrice(address asset) public view override returns (uint256) {\\n if (asset != CORRELATED_TOKEN) revert InvalidTokenAddress();\\n\\n uint256 exchangeRate = getUnderlyingAmount();\\n\\n if (snapshotInterval == 0) {\\n return _calculatePrice(exchangeRate);\\n }\\n\\n uint256 maxAllowedExchangeRate = getMaxAllowedExchangeRate();\\n\\n uint256 finalExchangeRate = (exchangeRate > maxAllowedExchangeRate && maxAllowedExchangeRate != 0)\\n ? maxAllowedExchangeRate\\n : exchangeRate;\\n\\n return _calculatePrice(finalExchangeRate);\\n }\\n\\n /**\\n * @notice Gets the maximum allowed exchange rate for token\\n * @return maxExchangeRate Maximum allowed exchange rate\\n */\\n function getMaxAllowedExchangeRate() public view returns (uint256) {\\n uint256 timeElapsed = block.timestamp - snapshotTimestamp;\\n uint256 maxExchangeRate = snapshotMaxExchangeRate +\\n (snapshotMaxExchangeRate * growthRatePerSecond * timeElapsed) /\\n 1e18;\\n return maxExchangeRate;\\n }\\n\\n /**\\n * @notice Gets the underlying amount for correlated token\\n * @return underlyingAmount Amount of underlying token\\n */\\n function getUnderlyingAmount() public view virtual returns (uint256);\\n\\n /**\\n * @notice Fetches price of the token based on an underlying exchange rate\\n * @param exchangeRate The underlying exchange rate to use\\n * @return price The price of the token in scaled decimal places\\n */\\n function _calculatePrice(uint256 exchangeRate) internal view returns (uint256) {\\n uint256 underlyingUSDPrice = RESILIENT_ORACLE.getPrice(UNDERLYING_TOKEN);\\n\\n IERC20Metadata token = IERC20Metadata(CORRELATED_TOKEN);\\n uint256 decimals = token.decimals();\\n\\n return (exchangeRate * underlyingUSDPrice) / (10 ** decimals);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n * @custom:error Unauthorized error is thrown if the call is not allowed\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = ACCESS_CONTROL_MANAGER.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x808b444fa4d1d440dc43de290f1eb59a64646ce9085028b286fa30346305872e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6101a0604052348015610010575f80fd5b5060405161155938038061155983398101604081905261002f916103a6565b6060810151608082015160a083015160e084015161010085015161012086015161014087015161016088015161018089015161006f6301e1338087610481565b5f81905515801561007f57505f85115b8061009357505f8054118015610093575084155b156100b1576040516353b7e64560e11b815260040160405180910390fd5b8315806100bc575082155b80156100c757505f85115b156100e55760405163b8a5589b60e01b815260040160405180910390fd5b6100ee896102eb565b6100f7886102eb565b610100876102eb565b610109826102eb565b6001600160a01b0398891660805296881660a05294871660c052600192909255600255600355506004919091551660e0528051610145906102eb565b6020810151610153906102eb565b60c08101516101679063ffffffff16610315565b80516001600160a01b03908116610140526020820151166101005260408101516001811115610198576101986104a0565b6101208160018111156101ad576101ad6104a0565b815250508060c0015163ffffffff166101608163ffffffff168152505060a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610208573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061022c91906104b4565b60ff166101805261010051610140516101605160405162439f4b60e91b81526001600160a01b03928316600482015263ffffffff90911660248201525f928392169063873e960090604401606060405180830381865afa158015610292573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102b691906104ea565b925050915081806102c5575080155b156102e357604051637616640160e01b815260040160405180910390fd5b505050610532565b6001600160a01b038116610312576040516342bcdf7f60e11b815260040160405180910390fd5b50565b805f036103125760405163273e150360e21b815260040160405180910390fd5b6040516101a081016001600160401b038111828210171561036457634e487b7160e01b5f52604160045260245ffd5b60405290565b80516001600160a01b0381168114610380575f80fd5b919050565b805160028110610380575f80fd5b805163ffffffff81168114610380575f80fd5b5f6101a082840312156103b7575f80fd5b6103bf610335565b6103c88361036a565b81526103d66020840161036a565b60208201526103e760408401610385565b60408201526103f86060840161036a565b60608201526104096080840161036a565b608082015261041a60a0840161036a565b60a082015261042b60c08401610393565b60c082015260e0838101519082015261010080840151908201526101208084015190820152610140808401519082015261016061046981850161036a565b90820152610180928301519281019290925250919050565b5f8261049b57634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52602160045260245ffd5b5f602082840312156104c4575f80fd5b815160ff811681146104d4575f80fd5b9392505050565b80518015158114610380575f80fd5b5f805f606084860312156104fc575f80fd5b610505846104db565b9250602084015161ffff8116811461051b575f80fd5b9150610529604085016104db565b90509250925092565b60805160a05160c05160e0516101005161012051610140516101605161018051610f596106005f395f81816101d9015261099d01525f81816103070152818161081b01526108f601525f818161038b015281816107f301526108ce01525f818161014601526107a701525f81816102e001528181610847015261092201525f818161022e0152610b9a01525f818161034c0152818161069c0152610a6d01525f818161019a015281816106740152610a4101525f81816102a6015281816103b00152610adb0152610f595ff3fe608060405234801561000f575f80fd5b506004361061013d575f3560e01c806369240426116100b45780639c43eb54116100795780639c43eb541461033e578063a4edcd4c14610347578063abb856131461036e578063ac5a693e14610376578063bdf13af21461037e578063f46f16c214610386575f80fd5b8063692404261461029957806369818a35146102a15780637fc4e4a0146102c8578063809d7b31146102db578063879ac8f814610302575f80fd5b806341976e091161010557806341976e091461021657806345be2dc7146102295780635213f9c814610250578063596efe6f14610265578063643d813d1461026e578063671528d414610281575f80fd5b806302125d091461014157806307d0413c1461017e57806329db1be6146101955780633dae7c22146101d45780634169d2451461020d575b5f80fd5b6101687f000000000000000000000000000000000000000000000000000000000000000081565b6040516101759190610c57565b60405180910390f35b61018760015481565b604051908152602001610175565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610175565b6101fb7f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff9091168152602001610175565b61018760045481565b610187610224366004610c7d565b6103ad565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b61026361025e366004610ca3565b61045e565b005b61018760025481565b61026361027c366004610cba565b6104cf565b6102896105a5565b6040519015158152602001610175565b6102636105e0565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6102636102d6366004610cba565b610729565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610175565b61018760035481565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6101876107a1565b6101875f5481565b6101876109dd565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161461040057604051630f58058360e11b815260040160405180910390fd5b5f6104096107a1565b90506001545f036104245761041d81610a2a565b9392505050565b5f61042d6109dd565b90505f818311801561043e57508115155b610448578261044a565b815b905061045581610a2a565b95945050505050565b61049c6040518060400160405280601781526020017f736574536e617073686f744761702875696e7432353629000000000000000000815250610b81565b6004546040518291907feb3716d3f8388c182853c1dc98b18931f3a600bbab31f2ff48631f6412e4997f905f90a3600455565b61050d6040518060400160405280601e81526020017f73657447726f777468526174652875696e743235362c75696e74323536290000815250610b81565b5f5461051d6301e1338084610cee565b5f81905515801561052d57505f82115b8061054157505f8054118015610541575081155b1561055f576040516353b7e64560e11b815260040160405180910390fd5b6001545f54827fa65cbeb0e28a8803a912daac67c472c160aa01e2c988755fa424f290321de6088560405161059691815260200190565b60405180910390a45060015550565b5f6001545f036105b457505f90565b5f6105bd6109dd565b9050805f036105cd575f91505090565b5f6105d66107a1565b9190911192915050565b6001546003546105f09042610d0d565b10806105fc5750600154155b1561060357565b5f61060c6107a1565b90505f6106176109dd565b9050600454818311610629578261062b565b815b6106359190610d26565b6002819055426003555f0361065d57604051635f18388760e01b815260040160405180910390fd5b60405163b62cad6960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063b62cad69906024015f604051808303815f87803b1580156106dd575f80fd5b505af11580156106ef573d5f803e3d5ffd5b505050506003546002547f2c8c8fcb8c77a0ca21dcc3ab8fc0ade761557e76b1240cb40ebbef9fcee00f7d60405160405180910390a35050565b6107676040518060400160405280601c81526020017f736574536e617073686f742875696e743235362c75696e743235362900000000815250610b81565b60028290556003819055604051819083907f2c8c8fcb8c77a0ca21dcc3ab8fc0ade761557e76b1240cb40ebbef9fcee00f7d905f90a35050565b5f8060017f000000000000000000000000000000000000000000000000000000000000000060018111156107d7576107d7610c43565b036108b75760405163a31426d160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f000000000000000000000000000000000000000000000000000000000000000063ffffffff1660248301527f0000000000000000000000000000000000000000000000000000000000000000169063a31426d190604401602060405180830381865afa15801561088c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b09190610d39565b905061098e565b60405163abca0eab60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f000000000000000000000000000000000000000000000000000000000000000063ffffffff1660248301527f0000000000000000000000000000000000000000000000000000000000000000169063abca0eab90604401602060405180830381865afa158015610967573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061098b9190610d39565b90505b670de0b6b3a7640000816109c37f0000000000000000000000000000000000000000000000000000000000000000600a610e30565b6109cd9190610e3e565b6109d79190610cee565b91505090565b5f80600354426109ed9190610d0d565b90505f670de0b6b3a7640000825f54600254610a099190610e3e565b610a139190610e3e565b610a1d9190610cee565b60025461041d9190610d26565b6040516341976e0960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f9182917f000000000000000000000000000000000000000000000000000000000000000016906341976e0990602401602060405180830381865afa158015610ab2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ad69190610d39565b90505f7f000000000000000000000000000000000000000000000000000000000000000090505f816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b39573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b5d9190610e55565b60ff169050610b6d81600a610e75565b610b778487610e3e565b6104559190610cee565b6040516318c5e8ab60e01b81525f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906318c5e8ab90610bd19033908690600401610eae565b602060405180830381865afa158015610bec573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c109190610ed9565b905080610c3f57333083604051634a3fa29360e01b8152600401610c3693929190610ef8565b60405180910390fd5b5050565b634e487b7160e01b5f52602160045260245ffd5b6020810160028310610c7757634e487b7160e01b5f52602160045260245ffd5b91905290565b5f60208284031215610c8d575f80fd5b81356001600160a01b038116811461041d575f80fd5b5f60208284031215610cb3575f80fd5b5035919050565b5f8060408385031215610ccb575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52601160045260245ffd5b5f82610d0857634e487b7160e01b5f52601260045260245ffd5b500490565b81810381811115610d2057610d20610cda565b92915050565b80820180821115610d2057610d20610cda565b5f60208284031215610d49575f80fd5b5051919050565b600181815b80851115610d8a57815f1904821115610d7057610d70610cda565b80851615610d7d57918102915b93841c9390800290610d55565b509250929050565b5f82610da057506001610d20565b81610dac57505f610d20565b8160018114610dc25760028114610dcc57610de8565b6001915050610d20565b60ff841115610ddd57610ddd610cda565b50506001821b610d20565b5060208310610133831016604e8410600b8410161715610e0b575081810a610d20565b610e158383610d50565b805f1904821115610e2857610e28610cda565b029392505050565b5f61041d60ff841683610d92565b8082028115828204841417610d2057610d20610cda565b5f60208284031215610e65575f80fd5b815160ff8116811461041d575f80fd5b5f61041d8383610d92565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f90610ed190830184610e80565b949350505050565b5f60208284031215610ee9575f80fd5b8151801515811461041d575f80fd5b6001600160a01b038481168252831660208201526060604082018190525f9061045590830184610e8056fea2646970667358221220dd4434cf5ec982b81a2a3a25f96ea3d5d76d95704500f208da19253bd6abc73b64736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061013d575f3560e01c806369240426116100b45780639c43eb54116100795780639c43eb541461033e578063a4edcd4c14610347578063abb856131461036e578063ac5a693e14610376578063bdf13af21461037e578063f46f16c214610386575f80fd5b8063692404261461029957806369818a35146102a15780637fc4e4a0146102c8578063809d7b31146102db578063879ac8f814610302575f80fd5b806341976e091161010557806341976e091461021657806345be2dc7146102295780635213f9c814610250578063596efe6f14610265578063643d813d1461026e578063671528d414610281575f80fd5b806302125d091461014157806307d0413c1461017e57806329db1be6146101955780633dae7c22146101d45780634169d2451461020d575b5f80fd5b6101687f000000000000000000000000000000000000000000000000000000000000000081565b6040516101759190610c57565b60405180910390f35b61018760015481565b604051908152602001610175565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610175565b6101fb7f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff9091168152602001610175565b61018760045481565b610187610224366004610c7d565b6103ad565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b61026361025e366004610ca3565b61045e565b005b61018760025481565b61026361027c366004610cba565b6104cf565b6102896105a5565b6040519015158152602001610175565b6102636105e0565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6102636102d6366004610cba565b610729565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610175565b61018760035481565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6101876107a1565b6101875f5481565b6101876109dd565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161461040057604051630f58058360e11b815260040160405180910390fd5b5f6104096107a1565b90506001545f036104245761041d81610a2a565b9392505050565b5f61042d6109dd565b90505f818311801561043e57508115155b610448578261044a565b815b905061045581610a2a565b95945050505050565b61049c6040518060400160405280601781526020017f736574536e617073686f744761702875696e7432353629000000000000000000815250610b81565b6004546040518291907feb3716d3f8388c182853c1dc98b18931f3a600bbab31f2ff48631f6412e4997f905f90a3600455565b61050d6040518060400160405280601e81526020017f73657447726f777468526174652875696e743235362c75696e74323536290000815250610b81565b5f5461051d6301e1338084610cee565b5f81905515801561052d57505f82115b8061054157505f8054118015610541575081155b1561055f576040516353b7e64560e11b815260040160405180910390fd5b6001545f54827fa65cbeb0e28a8803a912daac67c472c160aa01e2c988755fa424f290321de6088560405161059691815260200190565b60405180910390a45060015550565b5f6001545f036105b457505f90565b5f6105bd6109dd565b9050805f036105cd575f91505090565b5f6105d66107a1565b9190911192915050565b6001546003546105f09042610d0d565b10806105fc5750600154155b1561060357565b5f61060c6107a1565b90505f6106176109dd565b9050600454818311610629578261062b565b815b6106359190610d26565b6002819055426003555f0361065d57604051635f18388760e01b815260040160405180910390fd5b60405163b62cad6960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063b62cad69906024015f604051808303815f87803b1580156106dd575f80fd5b505af11580156106ef573d5f803e3d5ffd5b505050506003546002547f2c8c8fcb8c77a0ca21dcc3ab8fc0ade761557e76b1240cb40ebbef9fcee00f7d60405160405180910390a35050565b6107676040518060400160405280601c81526020017f736574536e617073686f742875696e743235362c75696e743235362900000000815250610b81565b60028290556003819055604051819083907f2c8c8fcb8c77a0ca21dcc3ab8fc0ade761557e76b1240cb40ebbef9fcee00f7d905f90a35050565b5f8060017f000000000000000000000000000000000000000000000000000000000000000060018111156107d7576107d7610c43565b036108b75760405163a31426d160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f000000000000000000000000000000000000000000000000000000000000000063ffffffff1660248301527f0000000000000000000000000000000000000000000000000000000000000000169063a31426d190604401602060405180830381865afa15801561088c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b09190610d39565b905061098e565b60405163abca0eab60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f000000000000000000000000000000000000000000000000000000000000000063ffffffff1660248301527f0000000000000000000000000000000000000000000000000000000000000000169063abca0eab90604401602060405180830381865afa158015610967573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061098b9190610d39565b90505b670de0b6b3a7640000816109c37f0000000000000000000000000000000000000000000000000000000000000000600a610e30565b6109cd9190610e3e565b6109d79190610cee565b91505090565b5f80600354426109ed9190610d0d565b90505f670de0b6b3a7640000825f54600254610a099190610e3e565b610a139190610e3e565b610a1d9190610cee565b60025461041d9190610d26565b6040516341976e0960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f9182917f000000000000000000000000000000000000000000000000000000000000000016906341976e0990602401602060405180830381865afa158015610ab2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ad69190610d39565b90505f7f000000000000000000000000000000000000000000000000000000000000000090505f816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b39573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b5d9190610e55565b60ff169050610b6d81600a610e75565b610b778487610e3e565b6104559190610cee565b6040516318c5e8ab60e01b81525f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906318c5e8ab90610bd19033908690600401610eae565b602060405180830381865afa158015610bec573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c109190610ed9565b905080610c3f57333083604051634a3fa29360e01b8152600401610c3693929190610ef8565b60405180910390fd5b5050565b634e487b7160e01b5f52602160045260245ffd5b6020810160028310610c7757634e487b7160e01b5f52602160045260245ffd5b91905290565b5f60208284031215610c8d575f80fd5b81356001600160a01b038116811461041d575f80fd5b5f60208284031215610cb3575f80fd5b5035919050565b5f8060408385031215610ccb575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52601160045260245ffd5b5f82610d0857634e487b7160e01b5f52601260045260245ffd5b500490565b81810381811115610d2057610d20610cda565b92915050565b80820180821115610d2057610d20610cda565b5f60208284031215610d49575f80fd5b5051919050565b600181815b80851115610d8a57815f1904821115610d7057610d70610cda565b80851615610d7d57918102915b93841c9390800290610d55565b509250929050565b5f82610da057506001610d20565b81610dac57505f610d20565b8160018114610dc25760028114610dcc57610de8565b6001915050610d20565b60ff841115610ddd57610ddd610cda565b50506001821b610d20565b5060208310610133831016604e8410600b8410161715610e0b575081810a610d20565b610e158383610d50565b805f1904821115610e2857610e28610cda565b029392505050565b5f61041d60ff841683610d92565b8082028115828204841417610d2057610d20610cda565b5f60208284031215610e65575f80fd5b815160ff8116811461041d575f80fd5b5f61041d8383610d92565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f90610ed190830184610e80565b949350505050565b5f60208284031215610ee9575f80fd5b8151801515811461041d575f80fd5b6001600160a01b038481168252831660208201526060604082018190525f9061045590830184610e8056fea2646970667358221220dd4434cf5ec982b81a2a3a25f96ea3d5d76d95704500f208da19253bd6abc73b64736f6c63430008190033", + "devdoc": { + "author": "Venus", + "details": "As a base price the oracle uses either the price of the Pendle market's asset (in this case PT_TO_ASSET rate should be used) or the price of the Pendle market's interest bearing token (e.g. wstETH for stETH; in this case PT_TO_SY rate should be used). Technically, interest bearing token is different from standardized yield (SY) token, but since SY is a wrapper around an interest bearing token, we can safely assume the prices of the two are equal. This is not always true for asset price though: using PT_TO_ASSET rate assumes that the yield token can be seamlessly redeemed for the underlying asset. In reality, this might not always be the case. For more details, see https://docs.pendle.finance/Developers/Contracts/StandardizedYield", + "kind": "dev", + "methods": { + "constructor": { + "custom:error": "InvalidDuration Thrown if the duration is invalid" + }, + "getMaxAllowedExchangeRate()": { + "returns": { + "_0": "maxExchangeRate Maximum allowed exchange rate" + } + }, + "getPrice(address)": { + "custom:error": "InvalidTokenAddress error is thrown if the token address is invalid", + "params": { + "asset": "Address of the token" + }, + "returns": { + "_0": "price The price of the token in scaled decimal places. It can be capped to a maximum value taking into account the growth rate" + } + }, + "getUnderlyingAmount()": { + "returns": { + "_0": "amount The amount of underlying token (either the market's asset or the yield token) for 1 PT, adjusted for decimals such that the result has the same precision as the underlying token" + } + }, + "isCapped()": { + "returns": { + "_0": "isCapped Boolean indicating if the price is capped" + } + }, + "setGrowthRate(uint256,uint256)": { + "custom:error": "InvalidGrowthRate error is thrown if the growth rate is invalid", + "custom:event": "Emits GrowthRateUpdated event on successful update of the growth rate", + "params": { + "_annualGrowthRate": "The annual growth rate to set", + "_snapshotInterval": "The snapshot interval to set" + } + }, + "setSnapshot(uint256,uint256)": { + "custom:event": "Emits SnapshotUpdated event on successful update of the snapshot", + "params": { + "_snapshotMaxExchangeRate": "The exchange rate to set", + "_snapshotTimestamp": "The timestamp to set" + } + }, + "setSnapshotGap(uint256)": { + "custom:event": "Emits SnapshotGapUpdated event on successful update of the snapshot gap", + "params": { + "_snapshotGap": "The snapshot gap to set" + } + }, + "updateSnapshot()": { + "custom:error": "InvalidSnapshotMaxExchangeRate error is thrown if the max snapshot exchange rate is zero", + "custom:event": "Emits SnapshotUpdated event on successful update of the snapshot" + } + }, + "stateVariables": { + "UNDERLYING_DECIMALS": { + "details": "We make an assumption that the underlying decimals will not change throughout the lifetime of the Pendle market" + } + }, + "title": "PendleOracle", + "version": 1 + }, + "userdoc": { + "errors": { + "InvalidDuration()": [ + { + "notice": "Thrown if the duration is invalid" + } + ], + "InvalidGrowthRate()": [ + { + "notice": "Thrown if the growth rate is invalid" + } + ], + "InvalidInitialSnapshot()": [ + { + "notice": "Thrown if the initial snapshot is invalid" + } + ], + "InvalidSnapshotMaxExchangeRate()": [ + { + "notice": "Thrown if the max snapshot exchange rate is invalid" + } + ], + "InvalidTokenAddress()": [ + { + "notice": "Thrown if the token address is invalid" + } + ], + "Unauthorized(address,address,string)": [ + { + "notice": "@notice Thrown when the action is prohibited by AccessControlManager" + } + ], + "ZeroAddressNotAllowed()": [ + { + "notice": "Thrown if the supplied address is a zero address where it is not allowed" + } + ], + "ZeroValueNotAllowed()": [ + { + "notice": "Thrown if the supplied value is 0 where it is not allowed" + } + ] + }, + "events": { + "GrowthRateUpdated(uint256,uint256,uint256,uint256)": { + "notice": "Emitted when the growth rate is updated" + }, + "SnapshotGapUpdated(uint256,uint256)": { + "notice": "Emitted when the snapshot gap is updated" + }, + "SnapshotUpdated(uint256,uint256)": { + "notice": "Emitted when the snapshot is updated" + } + }, + "kind": "user", + "methods": { + "ACCESS_CONTROL_MANAGER()": { + "notice": "Address of the AccessControlManager contract" + }, + "CORRELATED_TOKEN()": { + "notice": "Address of the correlated token" + }, + "MARKET()": { + "notice": "Address of the market" + }, + "PT_ORACLE()": { + "notice": "Address of the PT oracle" + }, + "RATE_KIND()": { + "notice": "Whether to use PT/SY (standardized yield token) rate or PT/market asset rate" + }, + "RESILIENT_ORACLE()": { + "notice": "Address of Resilient Oracle" + }, + "TWAP_DURATION()": { + "notice": "Twap duration for the oracle" + }, + "UNDERLYING_DECIMALS()": { + "notice": "Decimals of the underlying token" + }, + "UNDERLYING_TOKEN()": { + "notice": "Address of the underlying token" + }, + "constructor": { + "notice": "Constructor for the implementation contract." + }, + "getMaxAllowedExchangeRate()": { + "notice": "Gets the maximum allowed exchange rate for token" + }, + "getPrice(address)": { + "notice": "Fetches the price of the token" + }, + "getUnderlyingAmount()": { + "notice": "Fetches the amount of underlying token for 1 PT" + }, + "isCapped()": { + "notice": "Returns if the price is capped" + }, + "setGrowthRate(uint256,uint256)": { + "notice": "Sets the growth rate and snapshot interval" + }, + "setSnapshot(uint256,uint256)": { + "notice": "Directly sets the snapshot exchange rate and timestamp" + }, + "setSnapshotGap(uint256)": { + "notice": "Sets the snapshot gap" + }, + "snapshotGap()": { + "notice": "Gap to add when updating the snapshot" + }, + "snapshotInterval()": { + "notice": "Snapshot update interval" + }, + "snapshotMaxExchangeRate()": { + "notice": "Last stored snapshot maximum exchange rate" + }, + "snapshotTimestamp()": { + "notice": "Last stored snapshot timestamp" + }, + "updateSnapshot()": { + "notice": "Updates the snapshot price and timestamp" + } + }, + "notice": "This oracle fetches the price of a pendle token", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 6602, + "contract": "contracts/oracles/PendleOracle.sol:PendleOracle", + "label": "growthRatePerSecond", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 6605, + "contract": "contracts/oracles/PendleOracle.sol:PendleOracle", + "label": "snapshotInterval", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 6608, + "contract": "contracts/oracles/PendleOracle.sol:PendleOracle", + "label": "snapshotMaxExchangeRate", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 6611, + "contract": "contracts/oracles/PendleOracle.sol:PendleOracle", + "label": "snapshotTimestamp", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 6614, + "contract": "contracts/oracles/PendleOracle.sol:PendleOracle", + "label": "snapshotGap", + "offset": 0, + "slot": "4", + "type": "t_uint256" + } + ], + "types": { + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/bscmainnet_addresses.json b/deployments/bscmainnet_addresses.json index ca429cdb..5c46c523 100644 --- a/deployments/bscmainnet_addresses.json +++ b/deployments/bscmainnet_addresses.json @@ -30,6 +30,8 @@ "PendleOracle-PT-clisBNB-24APR2025_Reference_PtToAsset": "0x189BD17F0375589922faeDD56A86e53C42d82C0e", "PendleOracle-PT-clisBNB-24APR2025_Reference_PtToAsset_Implementation": "0xac9118c15B95bc9385CbfFe11035CB200E282bf4", "PendleOracle-PT-clisBNB-24APR2025_Reference_PtToAsset_Proxy": "0x189BD17F0375589922faeDD56A86e53C42d82C0e", + "PendleOracle-PT-clisBNB-25JUN2026": "0x0FfFBb55d51cD46cD10C7dc865Dc73BD76201310", + "PendleOracle-PT-clisBNB-25JUN2026_Reference_PtToAsset": "0xc94866f155FEA46C398385665B08B813D20DF802", "PendleOracle-PT-sUSDe-26JUN2025": "0xC407403fa78Bce509821D776b6Be7f91cC04474f", "PendleOracle-PT-sUSDe-26JUN2025_Reference_PtToAsset": "0xe4817DA70beE980fdBF0064c426086D4D72a6C72", "PythOracle": "0xb893E38162f55fb80B18Aa44da76FaDf8E9B2262", diff --git a/deployments/bsctestnet.json b/deployments/bsctestnet.json index 58637750..18c1e5bb 100644 --- a/deployments/bsctestnet.json +++ b/deployments/bsctestnet.json @@ -7647,6 +7647,510 @@ } ] }, + "PendleOracle-PT-clisBNB-25JUN2026": { + "address": "0x86EB1cE03e825CFD4516F385d7b90DE72B90BF69", + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "address", + "name": "ptOracle", + "type": "address" + }, + { + "internalType": "enum PendleOracle.RateKind", + "name": "rateKind", + "type": "uint8" + }, + { + "internalType": "address", + "name": "ptToken", + "type": "address" + }, + { + "internalType": "address", + "name": "underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "resilientOracle", + "type": "address" + }, + { + "internalType": "uint32", + "name": "twapDuration", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "annualGrowthRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "snapshotInterval", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSnapshotMaxExchangeRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSnapshotTimestamp", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager", + "type": "address" + }, + { + "internalType": "uint256", + "name": "snapshotGap", + "type": "uint256" + } + ], + "internalType": "struct PendleOracle.ConstructorParams", + "name": "params", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidDuration", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidGrowthRate", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialSnapshot", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSnapshotMaxExchangeRate", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTokenAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValueNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldGrowthRatePerSecond", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newGrowthRatePerSecond", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "oldSnapshotInterval", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSnapshotInterval", + "type": "uint256" + } + ], + "name": "GrowthRateUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldSnapshotGap", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newSnapshotGap", + "type": "uint256" + } + ], + "name": "SnapshotGapUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "maxExchangeRate", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "SnapshotUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "ACCESS_CONTROL_MANAGER", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CORRELATED_TOKEN", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MARKET", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PT_ORACLE", + "outputs": [ + { + "internalType": "contract IPendlePtOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RATE_KIND", + "outputs": [ + { + "internalType": "enum PendleOracle.RateKind", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESILIENT_ORACLE", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TWAP_DURATION", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNDERLYING_DECIMALS", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNDERLYING_TOKEN", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxAllowedExchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUnderlyingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "growthRatePerSecond", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isCapped", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_annualGrowthRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_snapshotInterval", + "type": "uint256" + } + ], + "name": "setGrowthRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_snapshotMaxExchangeRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_snapshotTimestamp", + "type": "uint256" + } + ], + "name": "setSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_snapshotGap", + "type": "uint256" + } + ], + "name": "setSnapshotGap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotGap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotInterval", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotMaxExchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "updateSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, "PendleOracle-PT-sUSDe-26JUN2025": { "address": "0x85201328baa52061E6648d9b4c285529411Cd33B", "abi": [ diff --git a/deployments/bsctestnet/PendleOracle-PT-clisBNB-25JUN2026.json b/deployments/bsctestnet/PendleOracle-PT-clisBNB-25JUN2026.json new file mode 100644 index 00000000..99f2fedd --- /dev/null +++ b/deployments/bsctestnet/PendleOracle-PT-clisBNB-25JUN2026.json @@ -0,0 +1,785 @@ +{ + "address": "0x86EB1cE03e825CFD4516F385d7b90DE72B90BF69", + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "address", + "name": "ptOracle", + "type": "address" + }, + { + "internalType": "enum PendleOracle.RateKind", + "name": "rateKind", + "type": "uint8" + }, + { + "internalType": "address", + "name": "ptToken", + "type": "address" + }, + { + "internalType": "address", + "name": "underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "resilientOracle", + "type": "address" + }, + { + "internalType": "uint32", + "name": "twapDuration", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "annualGrowthRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "snapshotInterval", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSnapshotMaxExchangeRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSnapshotTimestamp", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager", + "type": "address" + }, + { + "internalType": "uint256", + "name": "snapshotGap", + "type": "uint256" + } + ], + "internalType": "struct PendleOracle.ConstructorParams", + "name": "params", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidDuration", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidGrowthRate", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialSnapshot", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSnapshotMaxExchangeRate", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTokenAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValueNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldGrowthRatePerSecond", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newGrowthRatePerSecond", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "oldSnapshotInterval", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSnapshotInterval", + "type": "uint256" + } + ], + "name": "GrowthRateUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldSnapshotGap", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newSnapshotGap", + "type": "uint256" + } + ], + "name": "SnapshotGapUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "maxExchangeRate", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "SnapshotUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "ACCESS_CONTROL_MANAGER", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CORRELATED_TOKEN", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MARKET", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PT_ORACLE", + "outputs": [ + { + "internalType": "contract IPendlePtOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RATE_KIND", + "outputs": [ + { + "internalType": "enum PendleOracle.RateKind", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESILIENT_ORACLE", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TWAP_DURATION", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNDERLYING_DECIMALS", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNDERLYING_TOKEN", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxAllowedExchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUnderlyingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "growthRatePerSecond", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isCapped", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_annualGrowthRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_snapshotInterval", + "type": "uint256" + } + ], + "name": "setGrowthRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_snapshotMaxExchangeRate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_snapshotTimestamp", + "type": "uint256" + } + ], + "name": "setSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_snapshotGap", + "type": "uint256" + } + ], + "name": "setSnapshotGap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotGap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotInterval", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotMaxExchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "snapshotTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "updateSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xc1fa2287830f50eee710e74ffa70590072a0f6b9174dfe096e56bc2c27cb0332", + "receipt": { + "to": null, + "from": "0x33C6476F88eeA28D7E7900F759B4597704Ef95B7", + "contractAddress": "0x86EB1cE03e825CFD4516F385d7b90DE72B90BF69", + "transactionIndex": 0, + "gasUsed": "941190", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x00b047f166b107ef5f58db317b7b44a0ae752ad278623c2ddaf36b6806fefecb", + "transactionHash": "0xc1fa2287830f50eee710e74ffa70590072a0f6b9174dfe096e56bc2c27cb0332", + "logs": [], + "blockNumber": 83429580, + "cumulativeGasUsed": "941190", + "status": 1, + "byzantium": true + }, + "args": [ + { + "market": "0x0000000000000000000000000000000000000004", + "ptOracle": "0xa37A9127C302fEc17d456a6E1a5643a18a1779aD", + "rateKind": 1, + "ptToken": "0x60825e8eBbed5C32c1DAA7eA68ceCA70BEA65040", + "underlyingToken": "0xd2aF6A916Bc77764dc63742BC30f71AF4cF423F4", + "resilientOracle": "0x3cD69251D04A28d887Ac14cbe2E14c52F3D57823", + "twapDuration": 1800, + "annualGrowthRate": 0, + "snapshotInterval": 0, + "initialSnapshotMaxExchangeRate": 0, + "initialSnapshotTimestamp": 0, + "accessControlManager": "0x45f8a08F534f34A97187626E05d4b6648Eeaa9AA", + "snapshotGap": 0 + } + ], + "numDeployments": 1, + "solcInputHash": "b2af75c30578a1eadca811d3d7334646", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"ptOracle\",\"type\":\"address\"},{\"internalType\":\"enum PendleOracle.RateKind\",\"name\":\"rateKind\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"ptToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"underlyingToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resilientOracle\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"twapDuration\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"annualGrowthRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"snapshotInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"initialSnapshotMaxExchangeRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"initialSnapshotTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"accessControlManager\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"snapshotGap\",\"type\":\"uint256\"}],\"internalType\":\"struct PendleOracle.ConstructorParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidDuration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidGrowthRate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialSnapshot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSnapshotMaxExchangeRate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTokenAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldGrowthRatePerSecond\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newGrowthRatePerSecond\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldSnapshotInterval\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSnapshotInterval\",\"type\":\"uint256\"}],\"name\":\"GrowthRateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldSnapshotGap\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newSnapshotGap\",\"type\":\"uint256\"}],\"name\":\"SnapshotGapUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"maxExchangeRate\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"SnapshotUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ACCESS_CONTROL_MANAGER\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"CORRELATED_TOKEN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MARKET\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PT_ORACLE\",\"outputs\":[{\"internalType\":\"contract IPendlePtOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RATE_KIND\",\"outputs\":[{\"internalType\":\"enum PendleOracle.RateKind\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RESILIENT_ORACLE\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TWAP_DURATION\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UNDERLYING_DECIMALS\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UNDERLYING_TOKEN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getMaxAllowedExchangeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getUnderlyingAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"growthRatePerSecond\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isCapped\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_annualGrowthRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_snapshotInterval\",\"type\":\"uint256\"}],\"name\":\"setGrowthRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_snapshotMaxExchangeRate\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_snapshotTimestamp\",\"type\":\"uint256\"}],\"name\":\"setSnapshot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_snapshotGap\",\"type\":\"uint256\"}],\"name\":\"setSnapshotGap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"snapshotGap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"snapshotInterval\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"snapshotMaxExchangeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"snapshotTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateSnapshot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"As a base price the oracle uses either the price of the Pendle market's asset (in this case PT_TO_ASSET rate should be used) or the price of the Pendle market's interest bearing token (e.g. wstETH for stETH; in this case PT_TO_SY rate should be used). Technically, interest bearing token is different from standardized yield (SY) token, but since SY is a wrapper around an interest bearing token, we can safely assume the prices of the two are equal. This is not always true for asset price though: using PT_TO_ASSET rate assumes that the yield token can be seamlessly redeemed for the underlying asset. In reality, this might not always be the case. For more details, see https://docs.pendle.finance/Developers/Contracts/StandardizedYield\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:error\":\"InvalidDuration Thrown if the duration is invalid\"},\"getMaxAllowedExchangeRate()\":{\"returns\":{\"_0\":\"maxExchangeRate Maximum allowed exchange rate\"}},\"getPrice(address)\":{\"custom:error\":\"InvalidTokenAddress error is thrown if the token address is invalid\",\"params\":{\"asset\":\"Address of the token\"},\"returns\":{\"_0\":\"price The price of the token in scaled decimal places. It can be capped to a maximum value taking into account the growth rate\"}},\"getUnderlyingAmount()\":{\"returns\":{\"_0\":\"amount The amount of underlying token (either the market's asset or the yield token) for 1 PT, adjusted for decimals such that the result has the same precision as the underlying token\"}},\"isCapped()\":{\"returns\":{\"_0\":\"isCapped Boolean indicating if the price is capped\"}},\"setGrowthRate(uint256,uint256)\":{\"custom:error\":\"InvalidGrowthRate error is thrown if the growth rate is invalid\",\"custom:event\":\"Emits GrowthRateUpdated event on successful update of the growth rate\",\"params\":{\"_annualGrowthRate\":\"The annual growth rate to set\",\"_snapshotInterval\":\"The snapshot interval to set\"}},\"setSnapshot(uint256,uint256)\":{\"custom:event\":\"Emits SnapshotUpdated event on successful update of the snapshot\",\"params\":{\"_snapshotMaxExchangeRate\":\"The exchange rate to set\",\"_snapshotTimestamp\":\"The timestamp to set\"}},\"setSnapshotGap(uint256)\":{\"custom:event\":\"Emits SnapshotGapUpdated event on successful update of the snapshot gap\",\"params\":{\"_snapshotGap\":\"The snapshot gap to set\"}},\"updateSnapshot()\":{\"custom:error\":\"InvalidSnapshotMaxExchangeRate error is thrown if the max snapshot exchange rate is zero\",\"custom:event\":\"Emits SnapshotUpdated event on successful update of the snapshot\"}},\"stateVariables\":{\"UNDERLYING_DECIMALS\":{\"details\":\"We make an assumption that the underlying decimals will not change throughout the lifetime of the Pendle market\"}},\"title\":\"PendleOracle\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidDuration()\":[{\"notice\":\"Thrown if the duration is invalid\"}],\"InvalidGrowthRate()\":[{\"notice\":\"Thrown if the growth rate is invalid\"}],\"InvalidInitialSnapshot()\":[{\"notice\":\"Thrown if the initial snapshot is invalid\"}],\"InvalidSnapshotMaxExchangeRate()\":[{\"notice\":\"Thrown if the max snapshot exchange rate is invalid\"}],\"InvalidTokenAddress()\":[{\"notice\":\"Thrown if the token address is invalid\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"@notice Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}],\"ZeroValueNotAllowed()\":[{\"notice\":\"Thrown if the supplied value is 0 where it is not allowed\"}]},\"events\":{\"GrowthRateUpdated(uint256,uint256,uint256,uint256)\":{\"notice\":\"Emitted when the growth rate is updated\"},\"SnapshotGapUpdated(uint256,uint256)\":{\"notice\":\"Emitted when the snapshot gap is updated\"},\"SnapshotUpdated(uint256,uint256)\":{\"notice\":\"Emitted when the snapshot is updated\"}},\"kind\":\"user\",\"methods\":{\"ACCESS_CONTROL_MANAGER()\":{\"notice\":\"Address of the AccessControlManager contract\"},\"CORRELATED_TOKEN()\":{\"notice\":\"Address of the correlated token\"},\"MARKET()\":{\"notice\":\"Address of the market\"},\"PT_ORACLE()\":{\"notice\":\"Address of the PT oracle\"},\"RATE_KIND()\":{\"notice\":\"Whether to use PT/SY (standardized yield token) rate or PT/market asset rate\"},\"RESILIENT_ORACLE()\":{\"notice\":\"Address of Resilient Oracle\"},\"TWAP_DURATION()\":{\"notice\":\"Twap duration for the oracle\"},\"UNDERLYING_DECIMALS()\":{\"notice\":\"Decimals of the underlying token\"},\"UNDERLYING_TOKEN()\":{\"notice\":\"Address of the underlying token\"},\"constructor\":{\"notice\":\"Constructor for the implementation contract.\"},\"getMaxAllowedExchangeRate()\":{\"notice\":\"Gets the maximum allowed exchange rate for token\"},\"getPrice(address)\":{\"notice\":\"Fetches the price of the token\"},\"getUnderlyingAmount()\":{\"notice\":\"Fetches the amount of underlying token for 1 PT\"},\"isCapped()\":{\"notice\":\"Returns if the price is capped\"},\"setGrowthRate(uint256,uint256)\":{\"notice\":\"Sets the growth rate and snapshot interval\"},\"setSnapshot(uint256,uint256)\":{\"notice\":\"Directly sets the snapshot exchange rate and timestamp\"},\"setSnapshotGap(uint256)\":{\"notice\":\"Sets the snapshot gap\"},\"snapshotGap()\":{\"notice\":\"Gap to add when updating the snapshot\"},\"snapshotInterval()\":{\"notice\":\"Snapshot update interval\"},\"snapshotMaxExchangeRate()\":{\"notice\":\"Last stored snapshot maximum exchange rate\"},\"snapshotTimestamp()\":{\"notice\":\"Last stored snapshot timestamp\"},\"updateSnapshot()\":{\"notice\":\"Updates the snapshot price and timestamp\"}},\"notice\":\"This oracle fetches the price of a pendle token\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/oracles/PendleOracle.sol\":\"PendleOracle\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/validators.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\\nerror ZeroAddressNotAllowed();\\n\\n/// @notice Thrown if the supplied value is 0 where it is not allowed\\nerror ZeroValueNotAllowed();\\n\\n/// @notice Checks if the provided address is nonzero, reverts otherwise\\n/// @param address_ Address to check\\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\\nfunction ensureNonzeroAddress(address address_) pure {\\n if (address_ == address(0)) {\\n revert ZeroAddressNotAllowed();\\n }\\n}\\n\\n/// @notice Checks if the provided value is nonzero, reverts otherwise\\n/// @param value_ Value to check\\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\\nfunction ensureNonzeroValue(uint256 value_) pure {\\n if (value_ == 0) {\\n revert ZeroValueNotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xdb88e14d50dd21889ca3329d755673d022c47e8da005b6a545c7f69c2c4b7b86\",\"license\":\"BSD-3-Clause\"},\"contracts/interfaces/ICappedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface ICappedOracle {\\n function updateSnapshot() external;\\n}\\n\",\"keccak256\":\"0xad239e65b5e92b3486418c5ccca120247702251f9724cd96657c3cfdc7fedc31\",\"license\":\"BSD-3-Clause\"},\"contracts/interfaces/IPendlePtOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IPendlePtOracle {\\n function getPtToAssetRate(address market, uint32 duration) external view returns (uint256);\\n\\n function getPtToSyRate(address market, uint32 duration) external view returns (uint256);\\n\\n function getOracleState(\\n address market,\\n uint32 duration\\n )\\n external\\n view\\n returns (bool increaseCardinalityRequired, uint16 cardinalityRequired, bool oldestObservationSatisfied);\\n}\\n\",\"keccak256\":\"0x14d96d7f75397e4291288ef6367053bd970d95fc0c3e2a028b077f6342e0160a\",\"license\":\"BSD-3-Clause\"},\"contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"contracts/oracles/PendleOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IPendlePtOracle } from \\\"../interfaces/IPendlePtOracle.sol\\\";\\nimport { CorrelatedTokenOracle } from \\\"./common/CorrelatedTokenOracle.sol\\\";\\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\n/**\\n * @title PendleOracle\\n * @author Venus\\n * @notice This oracle fetches the price of a pendle token\\n * @dev As a base price the oracle uses either the price of the Pendle\\n * market's asset (in this case PT_TO_ASSET rate should be used) or\\n * the price of the Pendle market's interest bearing token (e.g. wstETH\\n * for stETH; in this case PT_TO_SY rate should be used). Technically,\\n * interest bearing token is different from standardized yield (SY) token,\\n * but since SY is a wrapper around an interest bearing token, we can safely\\n * assume the prices of the two are equal. This is not always true for asset\\n * price though: using PT_TO_ASSET rate assumes that the yield token can\\n * be seamlessly redeemed for the underlying asset. In reality, this might\\n * not always be the case. For more details, see\\n * https://docs.pendle.finance/Developers/Contracts/StandardizedYield\\n */\\ncontract PendleOracle is CorrelatedTokenOracle {\\n struct ConstructorParams {\\n /// @notice Pendle market\\n address market;\\n /// @notice Pendle oracle\\n address ptOracle;\\n /// @notice Either PT_TO_ASSET or PT_TO_SY\\n RateKind rateKind;\\n /// @notice Pendle PT token\\n address ptToken;\\n /// @notice Underlying token, can be either the market's asset or the interest bearing token\\n address underlyingToken;\\n /// @notice Resilient oracle to get the underlying token price from\\n address resilientOracle;\\n /// @notice TWAP duration to call Pendle oracle with\\n uint32 twapDuration;\\n /// @notice Annual growth rate of the underlying token\\n uint256 annualGrowthRate;\\n /// @notice Snapshot interval for the oracle\\n uint256 snapshotInterval;\\n /// @notice Initial exchange rate of the underlying token\\n uint256 initialSnapshotMaxExchangeRate;\\n /// @notice Initial timestamp of the underlying token\\n uint256 initialSnapshotTimestamp;\\n /// @notice Access control manager\\n address accessControlManager;\\n /// @notice Gap to add when updating the snapshot\\n uint256 snapshotGap;\\n }\\n\\n /// @notice Which asset to use as a base for the returned PT\\n /// price. Can be either a standardized yield token (SY), in\\n /// this case PT/SY price is returned, or the Pendle\\n /// market's asset directly.\\n enum RateKind {\\n PT_TO_ASSET,\\n PT_TO_SY\\n }\\n\\n /// @notice Address of the PT oracle\\n IPendlePtOracle public immutable PT_ORACLE;\\n\\n /// @notice Whether to use PT/SY (standardized yield token) rate\\n /// or PT/market asset rate\\n RateKind public immutable RATE_KIND;\\n\\n /// @notice Address of the market\\n address public immutable MARKET;\\n\\n /// @notice Twap duration for the oracle\\n uint32 public immutable TWAP_DURATION;\\n\\n /// @notice Decimals of the underlying token\\n /// @dev We make an assumption that the underlying decimals will\\n /// not change throughout the lifetime of the Pendle market\\n uint8 public immutable UNDERLYING_DECIMALS;\\n\\n /// @notice Thrown if the duration is invalid\\n error InvalidDuration();\\n\\n /**\\n * @notice Constructor for the implementation contract.\\n * @custom:error InvalidDuration Thrown if the duration is invalid\\n */\\n constructor(\\n ConstructorParams memory params\\n )\\n CorrelatedTokenOracle(\\n params.ptToken,\\n params.underlyingToken,\\n params.resilientOracle,\\n params.annualGrowthRate,\\n params.snapshotInterval,\\n params.initialSnapshotMaxExchangeRate,\\n params.initialSnapshotTimestamp,\\n params.accessControlManager,\\n params.snapshotGap\\n )\\n {\\n ensureNonzeroAddress(params.market);\\n ensureNonzeroAddress(params.ptOracle);\\n ensureNonzeroValue(params.twapDuration);\\n\\n MARKET = params.market;\\n PT_ORACLE = IPendlePtOracle(params.ptOracle);\\n RATE_KIND = params.rateKind;\\n TWAP_DURATION = params.twapDuration;\\n UNDERLYING_DECIMALS = IERC20Metadata(UNDERLYING_TOKEN).decimals();\\n\\n (bool increaseCardinalityRequired, , bool oldestObservationSatisfied) = PT_ORACLE.getOracleState(\\n MARKET,\\n TWAP_DURATION\\n );\\n if (increaseCardinalityRequired || !oldestObservationSatisfied) {\\n revert InvalidDuration();\\n }\\n }\\n\\n /// @notice Fetches the amount of underlying token for 1 PT\\n /// @return amount The amount of underlying token (either the market's asset\\n /// or the yield token) for 1 PT, adjusted for decimals such that the result\\n /// has the same precision as the underlying token\\n function getUnderlyingAmount() public view override returns (uint256) {\\n uint256 rate;\\n if (RATE_KIND == RateKind.PT_TO_SY) {\\n rate = PT_ORACLE.getPtToSyRate(MARKET, TWAP_DURATION);\\n } else {\\n rate = PT_ORACLE.getPtToAssetRate(MARKET, TWAP_DURATION);\\n }\\n return ((10 ** UNDERLYING_DECIMALS) * rate) / 1e18;\\n }\\n}\\n\",\"keccak256\":\"0xaa7963ac7657ea62079c2162cb4fc45524f8ffbbc6e84f89a5d4e54b71dc6025\",\"license\":\"BSD-3-Clause\"},\"contracts/oracles/common/CorrelatedTokenOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { OracleInterface, ResilientOracleInterface } from \\\"../../interfaces/OracleInterface.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"@venusprotocol/solidity-utilities/contracts/validators.sol\\\";\\nimport { SECONDS_PER_YEAR } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { ICappedOracle } from \\\"../../interfaces/ICappedOracle.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\n/**\\n * @title CorrelatedTokenOracle\\n * @notice This oracle fetches the price of a token that is correlated to another token.\\n */\\nabstract contract CorrelatedTokenOracle is OracleInterface, ICappedOracle {\\n /// @notice Address of the correlated token\\n address public immutable CORRELATED_TOKEN;\\n\\n /// @notice Address of the underlying token\\n address public immutable UNDERLYING_TOKEN;\\n\\n /// @notice Address of Resilient Oracle\\n ResilientOracleInterface public immutable RESILIENT_ORACLE;\\n\\n /// @notice Address of the AccessControlManager contract\\n IAccessControlManagerV8 public immutable ACCESS_CONTROL_MANAGER;\\n\\n //// @notice Growth rate percentage in seconds. Ex: 1e18 is 100%\\n uint256 public growthRatePerSecond;\\n\\n /// @notice Snapshot update interval\\n uint256 public snapshotInterval;\\n\\n /// @notice Last stored snapshot maximum exchange rate\\n uint256 public snapshotMaxExchangeRate;\\n\\n /// @notice Last stored snapshot timestamp\\n uint256 public snapshotTimestamp;\\n\\n /// @notice Gap to add when updating the snapshot\\n uint256 public snapshotGap;\\n\\n /// @notice Emitted when the snapshot is updated\\n event SnapshotUpdated(uint256 indexed maxExchangeRate, uint256 indexed timestamp);\\n\\n /// @notice Emitted when the growth rate is updated\\n event GrowthRateUpdated(\\n uint256 indexed oldGrowthRatePerSecond,\\n uint256 indexed newGrowthRatePerSecond,\\n uint256 indexed oldSnapshotInterval,\\n uint256 newSnapshotInterval\\n );\\n\\n /// @notice Emitted when the snapshot gap is updated\\n event SnapshotGapUpdated(uint256 indexed oldSnapshotGap, uint256 indexed newSnapshotGap);\\n\\n /// @notice Thrown if the token address is invalid\\n error InvalidTokenAddress();\\n\\n /// @notice Thrown if the growth rate is invalid\\n error InvalidGrowthRate();\\n\\n /// @notice Thrown if the initial snapshot is invalid\\n error InvalidInitialSnapshot();\\n\\n /// @notice Thrown if the max snapshot exchange rate is invalid\\n error InvalidSnapshotMaxExchangeRate();\\n\\n /// @notice @notice Thrown when the action is prohibited by AccessControlManager\\n error Unauthorized(address sender, address calledContract, string methodSignature);\\n\\n /**\\n * @notice Constructor for the implementation contract.\\n * @custom:error InvalidGrowthRate error is thrown if the growth rate is invalid\\n * @custom:error InvalidInitialSnapshot error is thrown if the initial snapshot values are invalid\\n */\\n constructor(\\n address _correlatedToken,\\n address _underlyingToken,\\n address _resilientOracle,\\n uint256 _annualGrowthRate,\\n uint256 _snapshotInterval,\\n uint256 _initialSnapshotMaxExchangeRate,\\n uint256 _initialSnapshotTimestamp,\\n address _accessControlManager,\\n uint256 _snapshotGap\\n ) {\\n growthRatePerSecond = _annualGrowthRate / SECONDS_PER_YEAR;\\n\\n if ((growthRatePerSecond == 0 && _snapshotInterval > 0) || (growthRatePerSecond > 0 && _snapshotInterval == 0))\\n revert InvalidGrowthRate();\\n\\n if ((_initialSnapshotMaxExchangeRate == 0 || _initialSnapshotTimestamp == 0) && _snapshotInterval > 0) {\\n revert InvalidInitialSnapshot();\\n }\\n\\n ensureNonzeroAddress(_correlatedToken);\\n ensureNonzeroAddress(_underlyingToken);\\n ensureNonzeroAddress(_resilientOracle);\\n ensureNonzeroAddress(_accessControlManager);\\n\\n CORRELATED_TOKEN = _correlatedToken;\\n UNDERLYING_TOKEN = _underlyingToken;\\n RESILIENT_ORACLE = ResilientOracleInterface(_resilientOracle);\\n snapshotInterval = _snapshotInterval;\\n\\n snapshotMaxExchangeRate = _initialSnapshotMaxExchangeRate;\\n snapshotTimestamp = _initialSnapshotTimestamp;\\n snapshotGap = _snapshotGap;\\n\\n ACCESS_CONTROL_MANAGER = IAccessControlManagerV8(_accessControlManager);\\n }\\n\\n /**\\n * @notice Directly sets the snapshot exchange rate and timestamp\\n * @param _snapshotMaxExchangeRate The exchange rate to set\\n * @param _snapshotTimestamp The timestamp to set\\n * @custom:event Emits SnapshotUpdated event on successful update of the snapshot\\n */\\n function setSnapshot(uint256 _snapshotMaxExchangeRate, uint256 _snapshotTimestamp) external {\\n _checkAccessAllowed(\\\"setSnapshot(uint256,uint256)\\\");\\n\\n snapshotMaxExchangeRate = _snapshotMaxExchangeRate;\\n snapshotTimestamp = _snapshotTimestamp;\\n\\n emit SnapshotUpdated(snapshotMaxExchangeRate, snapshotTimestamp);\\n }\\n\\n /**\\n * @notice Sets the growth rate and snapshot interval\\n * @param _annualGrowthRate The annual growth rate to set\\n * @param _snapshotInterval The snapshot interval to set\\n * @custom:error InvalidGrowthRate error is thrown if the growth rate is invalid\\n * @custom:event Emits GrowthRateUpdated event on successful update of the growth rate\\n */\\n function setGrowthRate(uint256 _annualGrowthRate, uint256 _snapshotInterval) external {\\n _checkAccessAllowed(\\\"setGrowthRate(uint256,uint256)\\\");\\n uint256 oldGrowthRatePerSecond = growthRatePerSecond;\\n\\n growthRatePerSecond = _annualGrowthRate / SECONDS_PER_YEAR;\\n\\n if ((growthRatePerSecond == 0 && _snapshotInterval > 0) || (growthRatePerSecond > 0 && _snapshotInterval == 0))\\n revert InvalidGrowthRate();\\n\\n emit GrowthRateUpdated(oldGrowthRatePerSecond, growthRatePerSecond, snapshotInterval, _snapshotInterval);\\n\\n snapshotInterval = _snapshotInterval;\\n }\\n\\n /**\\n * @notice Sets the snapshot gap\\n * @param _snapshotGap The snapshot gap to set\\n * @custom:event Emits SnapshotGapUpdated event on successful update of the snapshot gap\\n */\\n function setSnapshotGap(uint256 _snapshotGap) external {\\n _checkAccessAllowed(\\\"setSnapshotGap(uint256)\\\");\\n\\n emit SnapshotGapUpdated(snapshotGap, _snapshotGap);\\n\\n snapshotGap = _snapshotGap;\\n }\\n\\n /**\\n * @notice Returns if the price is capped\\n * @return isCapped Boolean indicating if the price is capped\\n */\\n function isCapped() external view virtual returns (bool) {\\n if (snapshotInterval == 0) {\\n return false;\\n }\\n\\n uint256 maxAllowedExchangeRate = getMaxAllowedExchangeRate();\\n if (maxAllowedExchangeRate == 0) {\\n return false;\\n }\\n\\n uint256 exchangeRate = getUnderlyingAmount();\\n\\n return exchangeRate > maxAllowedExchangeRate;\\n }\\n\\n /**\\n * @notice Updates the snapshot price and timestamp\\n * @custom:event Emits SnapshotUpdated event on successful update of the snapshot\\n * @custom:error InvalidSnapshotMaxExchangeRate error is thrown if the max snapshot exchange rate is zero\\n */\\n function updateSnapshot() public override {\\n if (block.timestamp - snapshotTimestamp < snapshotInterval || snapshotInterval == 0) return;\\n\\n uint256 exchangeRate = getUnderlyingAmount();\\n uint256 maxAllowedExchangeRate = getMaxAllowedExchangeRate();\\n\\n snapshotMaxExchangeRate =\\n (exchangeRate > maxAllowedExchangeRate ? maxAllowedExchangeRate : exchangeRate) +\\n snapshotGap;\\n snapshotTimestamp = block.timestamp;\\n\\n if (snapshotMaxExchangeRate == 0) revert InvalidSnapshotMaxExchangeRate();\\n\\n RESILIENT_ORACLE.updateAssetPrice(UNDERLYING_TOKEN);\\n emit SnapshotUpdated(snapshotMaxExchangeRate, snapshotTimestamp);\\n }\\n\\n /**\\n * @notice Fetches the price of the token\\n * @param asset Address of the token\\n * @return price The price of the token in scaled decimal places. It can be capped\\n * to a maximum value taking into account the growth rate\\n * @custom:error InvalidTokenAddress error is thrown if the token address is invalid\\n */\\n function getPrice(address asset) public view override returns (uint256) {\\n if (asset != CORRELATED_TOKEN) revert InvalidTokenAddress();\\n\\n uint256 exchangeRate = getUnderlyingAmount();\\n\\n if (snapshotInterval == 0) {\\n return _calculatePrice(exchangeRate);\\n }\\n\\n uint256 maxAllowedExchangeRate = getMaxAllowedExchangeRate();\\n\\n uint256 finalExchangeRate = (exchangeRate > maxAllowedExchangeRate && maxAllowedExchangeRate != 0)\\n ? maxAllowedExchangeRate\\n : exchangeRate;\\n\\n return _calculatePrice(finalExchangeRate);\\n }\\n\\n /**\\n * @notice Gets the maximum allowed exchange rate for token\\n * @return maxExchangeRate Maximum allowed exchange rate\\n */\\n function getMaxAllowedExchangeRate() public view returns (uint256) {\\n uint256 timeElapsed = block.timestamp - snapshotTimestamp;\\n uint256 maxExchangeRate = snapshotMaxExchangeRate +\\n (snapshotMaxExchangeRate * growthRatePerSecond * timeElapsed) /\\n 1e18;\\n return maxExchangeRate;\\n }\\n\\n /**\\n * @notice Gets the underlying amount for correlated token\\n * @return underlyingAmount Amount of underlying token\\n */\\n function getUnderlyingAmount() public view virtual returns (uint256);\\n\\n /**\\n * @notice Fetches price of the token based on an underlying exchange rate\\n * @param exchangeRate The underlying exchange rate to use\\n * @return price The price of the token in scaled decimal places\\n */\\n function _calculatePrice(uint256 exchangeRate) internal view returns (uint256) {\\n uint256 underlyingUSDPrice = RESILIENT_ORACLE.getPrice(UNDERLYING_TOKEN);\\n\\n IERC20Metadata token = IERC20Metadata(CORRELATED_TOKEN);\\n uint256 decimals = token.decimals();\\n\\n return (exchangeRate * underlyingUSDPrice) / (10 ** decimals);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n * @custom:error Unauthorized error is thrown if the call is not allowed\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = ACCESS_CONTROL_MANAGER.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert Unauthorized(msg.sender, address(this), signature);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x808b444fa4d1d440dc43de290f1eb59a64646ce9085028b286fa30346305872e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6101a0604052348015610010575f80fd5b5060405161155938038061155983398101604081905261002f916103a6565b6060810151608082015160a083015160e084015161010085015161012086015161014087015161016088015161018089015161006f6301e1338087610481565b5f81905515801561007f57505f85115b8061009357505f8054118015610093575084155b156100b1576040516353b7e64560e11b815260040160405180910390fd5b8315806100bc575082155b80156100c757505f85115b156100e55760405163b8a5589b60e01b815260040160405180910390fd5b6100ee896102eb565b6100f7886102eb565b610100876102eb565b610109826102eb565b6001600160a01b0398891660805296881660a05294871660c052600192909255600255600355506004919091551660e0528051610145906102eb565b6020810151610153906102eb565b60c08101516101679063ffffffff16610315565b80516001600160a01b03908116610140526020820151166101005260408101516001811115610198576101986104a0565b6101208160018111156101ad576101ad6104a0565b815250508060c0015163ffffffff166101608163ffffffff168152505060a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610208573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061022c91906104b4565b60ff166101805261010051610140516101605160405162439f4b60e91b81526001600160a01b03928316600482015263ffffffff90911660248201525f928392169063873e960090604401606060405180830381865afa158015610292573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102b691906104ea565b925050915081806102c5575080155b156102e357604051637616640160e01b815260040160405180910390fd5b505050610532565b6001600160a01b038116610312576040516342bcdf7f60e11b815260040160405180910390fd5b50565b805f036103125760405163273e150360e21b815260040160405180910390fd5b6040516101a081016001600160401b038111828210171561036457634e487b7160e01b5f52604160045260245ffd5b60405290565b80516001600160a01b0381168114610380575f80fd5b919050565b805160028110610380575f80fd5b805163ffffffff81168114610380575f80fd5b5f6101a082840312156103b7575f80fd5b6103bf610335565b6103c88361036a565b81526103d66020840161036a565b60208201526103e760408401610385565b60408201526103f86060840161036a565b60608201526104096080840161036a565b608082015261041a60a0840161036a565b60a082015261042b60c08401610393565b60c082015260e0838101519082015261010080840151908201526101208084015190820152610140808401519082015261016061046981850161036a565b90820152610180928301519281019290925250919050565b5f8261049b57634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52602160045260245ffd5b5f602082840312156104c4575f80fd5b815160ff811681146104d4575f80fd5b9392505050565b80518015158114610380575f80fd5b5f805f606084860312156104fc575f80fd5b610505846104db565b9250602084015161ffff8116811461051b575f80fd5b9150610529604085016104db565b90509250925092565b60805160a05160c05160e0516101005161012051610140516101605161018051610f596106005f395f81816101d9015261099d01525f81816103070152818161081b01526108f601525f818161038b015281816107f301526108ce01525f818161014601526107a701525f81816102e001528181610847015261092201525f818161022e0152610b9a01525f818161034c0152818161069c0152610a6d01525f818161019a015281816106740152610a4101525f81816102a6015281816103b00152610adb0152610f595ff3fe608060405234801561000f575f80fd5b506004361061013d575f3560e01c806369240426116100b45780639c43eb54116100795780639c43eb541461033e578063a4edcd4c14610347578063abb856131461036e578063ac5a693e14610376578063bdf13af21461037e578063f46f16c214610386575f80fd5b8063692404261461029957806369818a35146102a15780637fc4e4a0146102c8578063809d7b31146102db578063879ac8f814610302575f80fd5b806341976e091161010557806341976e091461021657806345be2dc7146102295780635213f9c814610250578063596efe6f14610265578063643d813d1461026e578063671528d414610281575f80fd5b806302125d091461014157806307d0413c1461017e57806329db1be6146101955780633dae7c22146101d45780634169d2451461020d575b5f80fd5b6101687f000000000000000000000000000000000000000000000000000000000000000081565b6040516101759190610c57565b60405180910390f35b61018760015481565b604051908152602001610175565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610175565b6101fb7f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff9091168152602001610175565b61018760045481565b610187610224366004610c7d565b6103ad565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b61026361025e366004610ca3565b61045e565b005b61018760025481565b61026361027c366004610cba565b6104cf565b6102896105a5565b6040519015158152602001610175565b6102636105e0565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6102636102d6366004610cba565b610729565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610175565b61018760035481565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6101876107a1565b6101875f5481565b6101876109dd565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161461040057604051630f58058360e11b815260040160405180910390fd5b5f6104096107a1565b90506001545f036104245761041d81610a2a565b9392505050565b5f61042d6109dd565b90505f818311801561043e57508115155b610448578261044a565b815b905061045581610a2a565b95945050505050565b61049c6040518060400160405280601781526020017f736574536e617073686f744761702875696e7432353629000000000000000000815250610b81565b6004546040518291907feb3716d3f8388c182853c1dc98b18931f3a600bbab31f2ff48631f6412e4997f905f90a3600455565b61050d6040518060400160405280601e81526020017f73657447726f777468526174652875696e743235362c75696e74323536290000815250610b81565b5f5461051d6301e1338084610cee565b5f81905515801561052d57505f82115b8061054157505f8054118015610541575081155b1561055f576040516353b7e64560e11b815260040160405180910390fd5b6001545f54827fa65cbeb0e28a8803a912daac67c472c160aa01e2c988755fa424f290321de6088560405161059691815260200190565b60405180910390a45060015550565b5f6001545f036105b457505f90565b5f6105bd6109dd565b9050805f036105cd575f91505090565b5f6105d66107a1565b9190911192915050565b6001546003546105f09042610d0d565b10806105fc5750600154155b1561060357565b5f61060c6107a1565b90505f6106176109dd565b9050600454818311610629578261062b565b815b6106359190610d26565b6002819055426003555f0361065d57604051635f18388760e01b815260040160405180910390fd5b60405163b62cad6960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063b62cad69906024015f604051808303815f87803b1580156106dd575f80fd5b505af11580156106ef573d5f803e3d5ffd5b505050506003546002547f2c8c8fcb8c77a0ca21dcc3ab8fc0ade761557e76b1240cb40ebbef9fcee00f7d60405160405180910390a35050565b6107676040518060400160405280601c81526020017f736574536e617073686f742875696e743235362c75696e743235362900000000815250610b81565b60028290556003819055604051819083907f2c8c8fcb8c77a0ca21dcc3ab8fc0ade761557e76b1240cb40ebbef9fcee00f7d905f90a35050565b5f8060017f000000000000000000000000000000000000000000000000000000000000000060018111156107d7576107d7610c43565b036108b75760405163a31426d160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f000000000000000000000000000000000000000000000000000000000000000063ffffffff1660248301527f0000000000000000000000000000000000000000000000000000000000000000169063a31426d190604401602060405180830381865afa15801561088c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b09190610d39565b905061098e565b60405163abca0eab60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f000000000000000000000000000000000000000000000000000000000000000063ffffffff1660248301527f0000000000000000000000000000000000000000000000000000000000000000169063abca0eab90604401602060405180830381865afa158015610967573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061098b9190610d39565b90505b670de0b6b3a7640000816109c37f0000000000000000000000000000000000000000000000000000000000000000600a610e30565b6109cd9190610e3e565b6109d79190610cee565b91505090565b5f80600354426109ed9190610d0d565b90505f670de0b6b3a7640000825f54600254610a099190610e3e565b610a139190610e3e565b610a1d9190610cee565b60025461041d9190610d26565b6040516341976e0960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f9182917f000000000000000000000000000000000000000000000000000000000000000016906341976e0990602401602060405180830381865afa158015610ab2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ad69190610d39565b90505f7f000000000000000000000000000000000000000000000000000000000000000090505f816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b39573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b5d9190610e55565b60ff169050610b6d81600a610e75565b610b778487610e3e565b6104559190610cee565b6040516318c5e8ab60e01b81525f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906318c5e8ab90610bd19033908690600401610eae565b602060405180830381865afa158015610bec573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c109190610ed9565b905080610c3f57333083604051634a3fa29360e01b8152600401610c3693929190610ef8565b60405180910390fd5b5050565b634e487b7160e01b5f52602160045260245ffd5b6020810160028310610c7757634e487b7160e01b5f52602160045260245ffd5b91905290565b5f60208284031215610c8d575f80fd5b81356001600160a01b038116811461041d575f80fd5b5f60208284031215610cb3575f80fd5b5035919050565b5f8060408385031215610ccb575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52601160045260245ffd5b5f82610d0857634e487b7160e01b5f52601260045260245ffd5b500490565b81810381811115610d2057610d20610cda565b92915050565b80820180821115610d2057610d20610cda565b5f60208284031215610d49575f80fd5b5051919050565b600181815b80851115610d8a57815f1904821115610d7057610d70610cda565b80851615610d7d57918102915b93841c9390800290610d55565b509250929050565b5f82610da057506001610d20565b81610dac57505f610d20565b8160018114610dc25760028114610dcc57610de8565b6001915050610d20565b60ff841115610ddd57610ddd610cda565b50506001821b610d20565b5060208310610133831016604e8410600b8410161715610e0b575081810a610d20565b610e158383610d50565b805f1904821115610e2857610e28610cda565b029392505050565b5f61041d60ff841683610d92565b8082028115828204841417610d2057610d20610cda565b5f60208284031215610e65575f80fd5b815160ff8116811461041d575f80fd5b5f61041d8383610d92565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f90610ed190830184610e80565b949350505050565b5f60208284031215610ee9575f80fd5b8151801515811461041d575f80fd5b6001600160a01b038481168252831660208201526060604082018190525f9061045590830184610e8056fea2646970667358221220dd4434cf5ec982b81a2a3a25f96ea3d5d76d95704500f208da19253bd6abc73b64736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061013d575f3560e01c806369240426116100b45780639c43eb54116100795780639c43eb541461033e578063a4edcd4c14610347578063abb856131461036e578063ac5a693e14610376578063bdf13af21461037e578063f46f16c214610386575f80fd5b8063692404261461029957806369818a35146102a15780637fc4e4a0146102c8578063809d7b31146102db578063879ac8f814610302575f80fd5b806341976e091161010557806341976e091461021657806345be2dc7146102295780635213f9c814610250578063596efe6f14610265578063643d813d1461026e578063671528d414610281575f80fd5b806302125d091461014157806307d0413c1461017e57806329db1be6146101955780633dae7c22146101d45780634169d2451461020d575b5f80fd5b6101687f000000000000000000000000000000000000000000000000000000000000000081565b6040516101759190610c57565b60405180910390f35b61018760015481565b604051908152602001610175565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610175565b6101fb7f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff9091168152602001610175565b61018760045481565b610187610224366004610c7d565b6103ad565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b61026361025e366004610ca3565b61045e565b005b61018760025481565b61026361027c366004610cba565b6104cf565b6102896105a5565b6040519015158152602001610175565b6102636105e0565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6102636102d6366004610cba565b610729565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610175565b61018760035481565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b6101876107a1565b6101875f5481565b6101876109dd565b6101bc7f000000000000000000000000000000000000000000000000000000000000000081565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161461040057604051630f58058360e11b815260040160405180910390fd5b5f6104096107a1565b90506001545f036104245761041d81610a2a565b9392505050565b5f61042d6109dd565b90505f818311801561043e57508115155b610448578261044a565b815b905061045581610a2a565b95945050505050565b61049c6040518060400160405280601781526020017f736574536e617073686f744761702875696e7432353629000000000000000000815250610b81565b6004546040518291907feb3716d3f8388c182853c1dc98b18931f3a600bbab31f2ff48631f6412e4997f905f90a3600455565b61050d6040518060400160405280601e81526020017f73657447726f777468526174652875696e743235362c75696e74323536290000815250610b81565b5f5461051d6301e1338084610cee565b5f81905515801561052d57505f82115b8061054157505f8054118015610541575081155b1561055f576040516353b7e64560e11b815260040160405180910390fd5b6001545f54827fa65cbeb0e28a8803a912daac67c472c160aa01e2c988755fa424f290321de6088560405161059691815260200190565b60405180910390a45060015550565b5f6001545f036105b457505f90565b5f6105bd6109dd565b9050805f036105cd575f91505090565b5f6105d66107a1565b9190911192915050565b6001546003546105f09042610d0d565b10806105fc5750600154155b1561060357565b5f61060c6107a1565b90505f6106176109dd565b9050600454818311610629578261062b565b815b6106359190610d26565b6002819055426003555f0361065d57604051635f18388760e01b815260040160405180910390fd5b60405163b62cad6960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063b62cad69906024015f604051808303815f87803b1580156106dd575f80fd5b505af11580156106ef573d5f803e3d5ffd5b505050506003546002547f2c8c8fcb8c77a0ca21dcc3ab8fc0ade761557e76b1240cb40ebbef9fcee00f7d60405160405180910390a35050565b6107676040518060400160405280601c81526020017f736574536e617073686f742875696e743235362c75696e743235362900000000815250610b81565b60028290556003819055604051819083907f2c8c8fcb8c77a0ca21dcc3ab8fc0ade761557e76b1240cb40ebbef9fcee00f7d905f90a35050565b5f8060017f000000000000000000000000000000000000000000000000000000000000000060018111156107d7576107d7610c43565b036108b75760405163a31426d160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f000000000000000000000000000000000000000000000000000000000000000063ffffffff1660248301527f0000000000000000000000000000000000000000000000000000000000000000169063a31426d190604401602060405180830381865afa15801561088c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b09190610d39565b905061098e565b60405163abca0eab60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f000000000000000000000000000000000000000000000000000000000000000063ffffffff1660248301527f0000000000000000000000000000000000000000000000000000000000000000169063abca0eab90604401602060405180830381865afa158015610967573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061098b9190610d39565b90505b670de0b6b3a7640000816109c37f0000000000000000000000000000000000000000000000000000000000000000600a610e30565b6109cd9190610e3e565b6109d79190610cee565b91505090565b5f80600354426109ed9190610d0d565b90505f670de0b6b3a7640000825f54600254610a099190610e3e565b610a139190610e3e565b610a1d9190610cee565b60025461041d9190610d26565b6040516341976e0960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f9182917f000000000000000000000000000000000000000000000000000000000000000016906341976e0990602401602060405180830381865afa158015610ab2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ad69190610d39565b90505f7f000000000000000000000000000000000000000000000000000000000000000090505f816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b39573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b5d9190610e55565b60ff169050610b6d81600a610e75565b610b778487610e3e565b6104559190610cee565b6040516318c5e8ab60e01b81525f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906318c5e8ab90610bd19033908690600401610eae565b602060405180830381865afa158015610bec573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c109190610ed9565b905080610c3f57333083604051634a3fa29360e01b8152600401610c3693929190610ef8565b60405180910390fd5b5050565b634e487b7160e01b5f52602160045260245ffd5b6020810160028310610c7757634e487b7160e01b5f52602160045260245ffd5b91905290565b5f60208284031215610c8d575f80fd5b81356001600160a01b038116811461041d575f80fd5b5f60208284031215610cb3575f80fd5b5035919050565b5f8060408385031215610ccb575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52601160045260245ffd5b5f82610d0857634e487b7160e01b5f52601260045260245ffd5b500490565b81810381811115610d2057610d20610cda565b92915050565b80820180821115610d2057610d20610cda565b5f60208284031215610d49575f80fd5b5051919050565b600181815b80851115610d8a57815f1904821115610d7057610d70610cda565b80851615610d7d57918102915b93841c9390800290610d55565b509250929050565b5f82610da057506001610d20565b81610dac57505f610d20565b8160018114610dc25760028114610dcc57610de8565b6001915050610d20565b60ff841115610ddd57610ddd610cda565b50506001821b610d20565b5060208310610133831016604e8410600b8410161715610e0b575081810a610d20565b610e158383610d50565b805f1904821115610e2857610e28610cda565b029392505050565b5f61041d60ff841683610d92565b8082028115828204841417610d2057610d20610cda565b5f60208284031215610e65575f80fd5b815160ff8116811461041d575f80fd5b5f61041d8383610d92565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f90610ed190830184610e80565b949350505050565b5f60208284031215610ee9575f80fd5b8151801515811461041d575f80fd5b6001600160a01b038481168252831660208201526060604082018190525f9061045590830184610e8056fea2646970667358221220dd4434cf5ec982b81a2a3a25f96ea3d5d76d95704500f208da19253bd6abc73b64736f6c63430008190033", + "devdoc": { + "author": "Venus", + "details": "As a base price the oracle uses either the price of the Pendle market's asset (in this case PT_TO_ASSET rate should be used) or the price of the Pendle market's interest bearing token (e.g. wstETH for stETH; in this case PT_TO_SY rate should be used). Technically, interest bearing token is different from standardized yield (SY) token, but since SY is a wrapper around an interest bearing token, we can safely assume the prices of the two are equal. This is not always true for asset price though: using PT_TO_ASSET rate assumes that the yield token can be seamlessly redeemed for the underlying asset. In reality, this might not always be the case. For more details, see https://docs.pendle.finance/Developers/Contracts/StandardizedYield", + "kind": "dev", + "methods": { + "constructor": { + "custom:error": "InvalidDuration Thrown if the duration is invalid" + }, + "getMaxAllowedExchangeRate()": { + "returns": { + "_0": "maxExchangeRate Maximum allowed exchange rate" + } + }, + "getPrice(address)": { + "custom:error": "InvalidTokenAddress error is thrown if the token address is invalid", + "params": { + "asset": "Address of the token" + }, + "returns": { + "_0": "price The price of the token in scaled decimal places. It can be capped to a maximum value taking into account the growth rate" + } + }, + "getUnderlyingAmount()": { + "returns": { + "_0": "amount The amount of underlying token (either the market's asset or the yield token) for 1 PT, adjusted for decimals such that the result has the same precision as the underlying token" + } + }, + "isCapped()": { + "returns": { + "_0": "isCapped Boolean indicating if the price is capped" + } + }, + "setGrowthRate(uint256,uint256)": { + "custom:error": "InvalidGrowthRate error is thrown if the growth rate is invalid", + "custom:event": "Emits GrowthRateUpdated event on successful update of the growth rate", + "params": { + "_annualGrowthRate": "The annual growth rate to set", + "_snapshotInterval": "The snapshot interval to set" + } + }, + "setSnapshot(uint256,uint256)": { + "custom:event": "Emits SnapshotUpdated event on successful update of the snapshot", + "params": { + "_snapshotMaxExchangeRate": "The exchange rate to set", + "_snapshotTimestamp": "The timestamp to set" + } + }, + "setSnapshotGap(uint256)": { + "custom:event": "Emits SnapshotGapUpdated event on successful update of the snapshot gap", + "params": { + "_snapshotGap": "The snapshot gap to set" + } + }, + "updateSnapshot()": { + "custom:error": "InvalidSnapshotMaxExchangeRate error is thrown if the max snapshot exchange rate is zero", + "custom:event": "Emits SnapshotUpdated event on successful update of the snapshot" + } + }, + "stateVariables": { + "UNDERLYING_DECIMALS": { + "details": "We make an assumption that the underlying decimals will not change throughout the lifetime of the Pendle market" + } + }, + "title": "PendleOracle", + "version": 1 + }, + "userdoc": { + "errors": { + "InvalidDuration()": [ + { + "notice": "Thrown if the duration is invalid" + } + ], + "InvalidGrowthRate()": [ + { + "notice": "Thrown if the growth rate is invalid" + } + ], + "InvalidInitialSnapshot()": [ + { + "notice": "Thrown if the initial snapshot is invalid" + } + ], + "InvalidSnapshotMaxExchangeRate()": [ + { + "notice": "Thrown if the max snapshot exchange rate is invalid" + } + ], + "InvalidTokenAddress()": [ + { + "notice": "Thrown if the token address is invalid" + } + ], + "Unauthorized(address,address,string)": [ + { + "notice": "@notice Thrown when the action is prohibited by AccessControlManager" + } + ], + "ZeroAddressNotAllowed()": [ + { + "notice": "Thrown if the supplied address is a zero address where it is not allowed" + } + ], + "ZeroValueNotAllowed()": [ + { + "notice": "Thrown if the supplied value is 0 where it is not allowed" + } + ] + }, + "events": { + "GrowthRateUpdated(uint256,uint256,uint256,uint256)": { + "notice": "Emitted when the growth rate is updated" + }, + "SnapshotGapUpdated(uint256,uint256)": { + "notice": "Emitted when the snapshot gap is updated" + }, + "SnapshotUpdated(uint256,uint256)": { + "notice": "Emitted when the snapshot is updated" + } + }, + "kind": "user", + "methods": { + "ACCESS_CONTROL_MANAGER()": { + "notice": "Address of the AccessControlManager contract" + }, + "CORRELATED_TOKEN()": { + "notice": "Address of the correlated token" + }, + "MARKET()": { + "notice": "Address of the market" + }, + "PT_ORACLE()": { + "notice": "Address of the PT oracle" + }, + "RATE_KIND()": { + "notice": "Whether to use PT/SY (standardized yield token) rate or PT/market asset rate" + }, + "RESILIENT_ORACLE()": { + "notice": "Address of Resilient Oracle" + }, + "TWAP_DURATION()": { + "notice": "Twap duration for the oracle" + }, + "UNDERLYING_DECIMALS()": { + "notice": "Decimals of the underlying token" + }, + "UNDERLYING_TOKEN()": { + "notice": "Address of the underlying token" + }, + "constructor": { + "notice": "Constructor for the implementation contract." + }, + "getMaxAllowedExchangeRate()": { + "notice": "Gets the maximum allowed exchange rate for token" + }, + "getPrice(address)": { + "notice": "Fetches the price of the token" + }, + "getUnderlyingAmount()": { + "notice": "Fetches the amount of underlying token for 1 PT" + }, + "isCapped()": { + "notice": "Returns if the price is capped" + }, + "setGrowthRate(uint256,uint256)": { + "notice": "Sets the growth rate and snapshot interval" + }, + "setSnapshot(uint256,uint256)": { + "notice": "Directly sets the snapshot exchange rate and timestamp" + }, + "setSnapshotGap(uint256)": { + "notice": "Sets the snapshot gap" + }, + "snapshotGap()": { + "notice": "Gap to add when updating the snapshot" + }, + "snapshotInterval()": { + "notice": "Snapshot update interval" + }, + "snapshotMaxExchangeRate()": { + "notice": "Last stored snapshot maximum exchange rate" + }, + "snapshotTimestamp()": { + "notice": "Last stored snapshot timestamp" + }, + "updateSnapshot()": { + "notice": "Updates the snapshot price and timestamp" + } + }, + "notice": "This oracle fetches the price of a pendle token", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 6754, + "contract": "contracts/oracles/PendleOracle.sol:PendleOracle", + "label": "growthRatePerSecond", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 6757, + "contract": "contracts/oracles/PendleOracle.sol:PendleOracle", + "label": "snapshotInterval", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 6760, + "contract": "contracts/oracles/PendleOracle.sol:PendleOracle", + "label": "snapshotMaxExchangeRate", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 6763, + "contract": "contracts/oracles/PendleOracle.sol:PendleOracle", + "label": "snapshotTimestamp", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 6766, + "contract": "contracts/oracles/PendleOracle.sol:PendleOracle", + "label": "snapshotGap", + "offset": 0, + "slot": "4", + "type": "t_uint256" + } + ], + "types": { + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/deployments/bsctestnet/solcInputs/b2af75c30578a1eadca811d3d7334646.json b/deployments/bsctestnet/solcInputs/b2af75c30578a1eadca811d3d7334646.json new file mode 100644 index 00000000..4527d4ad --- /dev/null +++ b/deployments/bsctestnet/solcInputs/b2af75c30578a1eadca811d3d7334646.json @@ -0,0 +1,340 @@ +{ + "language": "Solidity", + "sources": { + "@chainlink/contracts/src/v0.8/interfaces/AggregatorInterface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorInterface {\n function latestAnswer() external view returns (int256);\n\n function latestTimestamp() external view returns (uint256);\n\n function latestRound() external view returns (uint256);\n\n function getAnswer(uint256 roundId) external view returns (int256);\n\n function getTimestamp(uint256 roundId) external view returns (uint256);\n\n event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);\n\n event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);\n}\n" + }, + "@chainlink/contracts/src/v0.8/interfaces/AggregatorV2V3Interface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./AggregatorInterface.sol\";\nimport \"./AggregatorV3Interface.sol\";\n\ninterface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {}\n" + }, + "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n function decimals() external view returns (uint8);\n\n function description() external view returns (string memory);\n\n function version() external view returns (uint256);\n\n function getRoundData(uint80 _roundId)\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(address from, address to, uint256 amount) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\n\nimport \"./IAccessControlManagerV8.sol\";\n\n/**\n * @title AccessControlledV8\n * @author Venus\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\n */\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\n /// @notice Access control manager contract\n IAccessControlManagerV8 internal _accessControlManager;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when access control manager contract address is changed\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\n\n /// @notice Thrown when the action is prohibited by AccessControlManager\n error Unauthorized(address sender, address calledContract, string methodSignature);\n\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Sets the address of AccessControlManager\n * @dev Admin function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n * @custom:event Emits NewAccessControlManager event\n * @custom:access Only Governance\n */\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Returns the address of the access control manager contract\n */\n function accessControlManager() external view returns (IAccessControlManagerV8) {\n return _accessControlManager;\n }\n\n /**\n * @dev Internal function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n */\n function _setAccessControlManager(address accessControlManager_) internal {\n require(address(accessControlManager_) != address(0), \"invalid acess control manager address\");\n address oldAccessControlManager = address(_accessControlManager);\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\n }\n\n /**\n * @notice Reverts if the call is not allowed by AccessControlManager\n * @param signature Method signature\n */\n function _checkAccessAllowed(string memory signature) internal view {\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\n\n if (!isAllowedToCall) {\n revert Unauthorized(msg.sender, address(this), signature);\n }\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport \"@openzeppelin/contracts/access/IAccessControl.sol\";\n\n/**\n * @title IAccessControlManagerV8\n * @author Venus\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\n */\ninterface IAccessControlManagerV8 is IAccessControl {\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\n\n function revokeCallPermission(\n address contractAddress,\n string calldata functionSig,\n address accountToRevoke\n ) external;\n\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\n\n function hasPermission(\n address account,\n address contractAddress,\n string calldata functionSig\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/solidity-utilities/contracts/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\nuint256 constant EXP_SCALE = 1e18;\n\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\nuint256 constant MANTISSA_ONE = EXP_SCALE;\n\n/// @dev The approximate number of seconds per year\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\n" + }, + "@venusprotocol/solidity-utilities/contracts/validators.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\nerror ZeroAddressNotAllowed();\n\n/// @notice Thrown if the supplied value is 0 where it is not allowed\nerror ZeroValueNotAllowed();\n\n/// @notice Checks if the provided address is nonzero, reverts otherwise\n/// @param address_ Address to check\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\nfunction ensureNonzeroAddress(address address_) pure {\n if (address_ == address(0)) {\n revert ZeroAddressNotAllowed();\n }\n}\n\n/// @notice Checks if the provided value is nonzero, reverts otherwise\n/// @param value_ Value to check\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\nfunction ensureNonzeroValue(uint256 value_) pure {\n if (value_ == 0) {\n revert ZeroValueNotAllowed();\n }\n}\n" + }, + "contracts/hardhat-dependency-compiler/@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >0.0.0;\nimport '@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol';\n" + }, + "contracts/hardhat-dependency-compiler/hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >0.0.0;\nimport 'hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol';\n" + }, + "contracts/hardhat-dependency-compiler/hardhat-deploy/solc_0.8/proxy/OptimizedTransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >0.0.0;\nimport 'hardhat-deploy/solc_0.8/proxy/OptimizedTransparentUpgradeableProxy.sol';\n" + }, + "contracts/interfaces/FeedRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface FeedRegistryInterface {\n function latestRoundDataByName(\n string memory base,\n string memory quote\n )\n external\n view\n returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n function decimalsByName(string memory base, string memory quote) external view returns (uint8);\n}\n" + }, + "contracts/interfaces/IAccountant.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ninterface IAccountant {\n function getRateSafe() external view returns (uint256);\n}\n" + }, + "contracts/interfaces/IAnkrBNB.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ninterface IAnkrBNB {\n function sharesToBonds(uint256 amount) external view returns (uint256);\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/interfaces/IAsBNB.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ninterface IAsBNB {\n function minter() external view returns (address);\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/interfaces/IAsBNBMinter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ninterface IAsBNBMinter {\n function convertToTokens(uint256 amount) external view returns (uint256);\n}\n" + }, + "contracts/interfaces/ICappedOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ninterface ICappedOracle {\n function updateSnapshot() external;\n}\n" + }, + "contracts/interfaces/IERC4626.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ninterface IERC4626 {\n function convertToAssets(uint256 shares) external view returns (uint256);\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/interfaces/IEtherFiLiquidityPool.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ninterface IEtherFiLiquidityPool {\n function amountForShare(uint256 _share) external view returns (uint256);\n}\n" + }, + "contracts/interfaces/IPendlePtOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ninterface IPendlePtOracle {\n function getPtToAssetRate(address market, uint32 duration) external view returns (uint256);\n\n function getPtToSyRate(address market, uint32 duration) external view returns (uint256);\n\n function getOracleState(\n address market,\n uint32 duration\n )\n external\n view\n returns (bool increaseCardinalityRequired, uint16 cardinalityRequired, bool oldestObservationSatisfied);\n}\n" + }, + "contracts/interfaces/IPStakePool.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ninterface IPStakePool {\n struct Data {\n uint256 totalWei;\n uint256 poolTokenSupply;\n }\n\n /**\n * @dev The current exchange rate for converting stkBNB to BNB.\n */\n function exchangeRate() external view returns (Data memory);\n}\n" + }, + "contracts/interfaces/ISFrax.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ninterface ISFrax {\n function convertToAssets(uint256 shares) external view returns (uint256);\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/interfaces/ISfrxEthFraxOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ninterface ISfrxEthFraxOracle {\n function getPrices() external view returns (bool _isbadData, uint256 _priceLow, uint256 _priceHigh);\n}\n" + }, + "contracts/interfaces/IStaderStakeManager.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ninterface IStaderStakeManager {\n function convertBnbXToBnb(uint256 _amount) external view returns (uint256);\n}\n" + }, + "contracts/interfaces/IStETH.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IStETH {\n function getPooledEthByShares(uint256 _sharesAmount) external view returns (uint256);\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/interfaces/ISynclubStakeManager.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ninterface ISynclubStakeManager {\n function convertSnBnbToBnb(uint256 _amount) external view returns (uint256);\n}\n" + }, + "contracts/interfaces/IWBETH.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ninterface IWBETH {\n function exchangeRate() external view returns (uint256);\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/interfaces/IZkETH.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IZkETH {\n function LSTPerToken() external view returns (uint256);\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/interfaces/OracleInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface OracleInterface {\n function getPrice(address asset) external view returns (uint256);\n}\n\ninterface ResilientOracleInterface is OracleInterface {\n function updatePrice(address vToken) external;\n\n function updateAssetPrice(address asset) external;\n\n function getUnderlyingPrice(address vToken) external view returns (uint256);\n}\n\ninterface BoundValidatorInterface {\n function validatePriceWithAnchorPrice(\n address asset,\n uint256 reporterPrice,\n uint256 anchorPrice\n ) external view returns (bool);\n}\n" + }, + "contracts/interfaces/PublicResolverInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity ^0.8.25;\n\ninterface PublicResolverInterface {\n function addr(bytes32 node) external view returns (address payable);\n}\n" + }, + "contracts/interfaces/SIDRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity ^0.8.25;\n\ninterface SIDRegistryInterface {\n function resolver(bytes32 node) external view returns (address);\n}\n" + }, + "contracts/interfaces/VBep20Interface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\ninterface VBep20Interface is IERC20Metadata {\n /**\n * @notice Underlying asset for this VToken\n */\n function underlying() external view returns (address);\n}\n" + }, + "contracts/lib/Transient.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nlibrary Transient {\n /**\n * @notice Cache the asset price into transient storage\n * @param key address of the asset\n * @param value asset price\n */\n function cachePrice(bytes32 cacheSlot, address key, uint256 value) internal {\n bytes32 slot = keccak256(abi.encode(cacheSlot, key));\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @notice Read cached price from transient storage\n * @param key address of the asset\n * @return value cached asset price\n */\n function readCachedPrice(bytes32 cacheSlot, address key) internal view returns (uint256 value) {\n bytes32 slot = keccak256(abi.encode(cacheSlot, key));\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n}\n" + }, + "contracts/oracles/AnkrBNBOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IAnkrBNB } from \"../interfaces/IAnkrBNB.sol\";\nimport { CorrelatedTokenOracle } from \"./common/CorrelatedTokenOracle.sol\";\nimport { EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\n\n/**\n * @title AnkrBNBOracle\n * @author Venus\n * @notice This oracle fetches the price of ankrBNB asset\n */\ncontract AnkrBNBOracle is CorrelatedTokenOracle {\n /// @notice This is used as token address of BNB on BSC\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Constructor for the implementation contract.\n constructor(\n address ankrBNB,\n address resilientOracle,\n uint256 annualGrowthRate,\n uint256 _snapshotInterval,\n uint256 initialSnapshotMaxExchangeRate,\n uint256 initialSnapshotTimestamp,\n address accessControlManager,\n uint256 _snapshotGap\n )\n CorrelatedTokenOracle(\n ankrBNB,\n NATIVE_TOKEN_ADDR,\n resilientOracle,\n annualGrowthRate,\n _snapshotInterval,\n initialSnapshotMaxExchangeRate,\n initialSnapshotTimestamp,\n accessControlManager,\n _snapshotGap\n )\n {}\n\n /**\n * @notice Fetches the amount of BNB for 1 ankrBNB\n * @return amount The amount of BNB for ankrBNB\n */\n function getUnderlyingAmount() public view override returns (uint256) {\n return IAnkrBNB(CORRELATED_TOKEN).sharesToBonds(EXP_SCALE);\n }\n}\n" + }, + "contracts/oracles/AsBNBOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IAsBNB } from \"../interfaces/IAsBNB.sol\";\nimport { IAsBNBMinter } from \"../interfaces/IAsBNBMinter.sol\";\nimport { EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\nimport { CorrelatedTokenOracle } from \"./common/CorrelatedTokenOracle.sol\";\n\n/**\n * @title asBNBOracle\n * @author Venus\n * @notice This oracle fetches the price of asBNB asset\n */\ncontract AsBNBOracle is CorrelatedTokenOracle {\n /// @notice Constructor for the implementation contract.\n constructor(\n address asBNB,\n address slisBNB,\n address resilientOracle,\n uint256 annualGrowthRate,\n uint256 _snapshotInterval,\n uint256 initialSnapshotMaxExchangeRate,\n uint256 initialSnapshotTimestamp,\n address accessControlManager,\n uint256 _snapshotGap\n )\n CorrelatedTokenOracle(\n asBNB,\n slisBNB,\n resilientOracle,\n annualGrowthRate,\n _snapshotInterval,\n initialSnapshotMaxExchangeRate,\n initialSnapshotTimestamp,\n accessControlManager,\n _snapshotGap\n )\n {}\n\n /**\n * @notice Fetches the amount of slisBNB for 1 asBNB\n * @return price The amount of slisBNB for asBNB\n */\n function getUnderlyingAmount() public view override returns (uint256) {\n IAsBNBMinter minter = IAsBNBMinter(IAsBNB(CORRELATED_TOKEN).minter());\n return minter.convertToTokens(EXP_SCALE);\n }\n}\n" + }, + "contracts/oracles/BinanceOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"../interfaces/VBep20Interface.sol\";\nimport \"../interfaces/SIDRegistryInterface.sol\";\nimport \"../interfaces/FeedRegistryInterface.sol\";\nimport \"../interfaces/PublicResolverInterface.sol\";\nimport \"../interfaces/OracleInterface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport \"../interfaces/OracleInterface.sol\";\n\n/**\n * @title BinanceOracle\n * @author Venus\n * @notice This oracle fetches price of assets from Binance.\n */\ncontract BinanceOracle is AccessControlledV8, OracleInterface {\n /// @notice Used to fetch feed registry address.\n address public sidRegistryAddress;\n\n /// @notice Set this as asset address for BNB. This is the underlying address for vBNB\n address public constant BNB_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Max stale period configuration for assets\n mapping(string => uint256) public maxStalePeriod;\n\n /// @notice Override symbols to be compatible with Binance feed registry\n mapping(string => string) public symbols;\n\n /// @notice Used to fetch price of assets used directly when space ID is not supported by current chain.\n address public feedRegistryAddress;\n\n /// @notice Emits when asset stale period is updated.\n event MaxStalePeriodAdded(string indexed asset, uint256 maxStalePeriod);\n\n /// @notice Emits when symbol of the asset is updated.\n event SymbolOverridden(string indexed symbol, string overriddenSymbol);\n\n /// @notice Emits when address of feed registry is updated.\n event FeedRegistryUpdated(address indexed oldFeedRegistry, address indexed newFeedRegistry);\n\n /**\n * @notice Checks whether an address is null or not\n */\n modifier notNullAddress(address someone) {\n if (someone == address(0)) revert(\"can't be zero address\");\n _;\n }\n\n /// @notice Constructor for the implementation contract.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Sets the contracts required to fetch prices\n * @param _sidRegistryAddress Address of SID registry\n * @param _acm Address of the access control manager contract\n */\n function initialize(address _sidRegistryAddress, address _acm) external initializer {\n sidRegistryAddress = _sidRegistryAddress;\n __AccessControlled_init(_acm);\n }\n\n /**\n * @notice Used to set the max stale period of an asset\n * @param symbol The symbol of the asset\n * @param _maxStalePeriod The max stake period\n */\n function setMaxStalePeriod(string memory symbol, uint256 _maxStalePeriod) external {\n _checkAccessAllowed(\"setMaxStalePeriod(string,uint256)\");\n if (_maxStalePeriod == 0) revert(\"stale period can't be zero\");\n if (bytes(symbol).length == 0) revert(\"symbol cannot be empty\");\n\n maxStalePeriod[symbol] = _maxStalePeriod;\n emit MaxStalePeriodAdded(symbol, _maxStalePeriod);\n }\n\n /**\n * @notice Used to override a symbol when fetching price\n * @param symbol The symbol to override\n * @param overrideSymbol The symbol after override\n */\n function setSymbolOverride(string calldata symbol, string calldata overrideSymbol) external {\n _checkAccessAllowed(\"setSymbolOverride(string,string)\");\n if (bytes(symbol).length == 0) revert(\"symbol cannot be empty\");\n\n symbols[symbol] = overrideSymbol;\n emit SymbolOverridden(symbol, overrideSymbol);\n }\n\n /**\n * @notice Used to set feed registry address when current chain does not support space ID.\n * @param newfeedRegistryAddress Address of new feed registry.\n */\n function setFeedRegistryAddress(\n address newfeedRegistryAddress\n ) external notNullAddress(newfeedRegistryAddress) onlyOwner {\n if (sidRegistryAddress != address(0)) revert(\"sidRegistryAddress must be zero\");\n emit FeedRegistryUpdated(feedRegistryAddress, newfeedRegistryAddress);\n feedRegistryAddress = newfeedRegistryAddress;\n }\n\n /**\n * @notice Uses Space ID to fetch the feed registry address\n * @return feedRegistryAddress Address of binance oracle feed registry.\n */\n function getFeedRegistryAddress() public view returns (address) {\n bytes32 nodeHash = 0x94fe3821e0768eb35012484db4df61890f9a6ca5bfa984ef8ff717e73139faff;\n\n SIDRegistryInterface sidRegistry = SIDRegistryInterface(sidRegistryAddress);\n address publicResolverAddress = sidRegistry.resolver(nodeHash);\n PublicResolverInterface publicResolver = PublicResolverInterface(publicResolverAddress);\n\n return publicResolver.addr(nodeHash);\n }\n\n /**\n * @notice Gets the price of a asset from the binance oracle\n * @param asset Address of the asset\n * @return Price in USD\n */\n function getPrice(address asset) public view returns (uint256) {\n string memory symbol;\n uint256 decimals;\n\n if (asset == BNB_ADDR) {\n symbol = \"BNB\";\n decimals = 18;\n } else {\n IERC20Metadata token = IERC20Metadata(asset);\n symbol = token.symbol();\n decimals = token.decimals();\n }\n\n string memory overrideSymbol = symbols[symbol];\n\n if (bytes(overrideSymbol).length != 0) {\n symbol = overrideSymbol;\n }\n\n return _getPrice(symbol, decimals);\n }\n\n function _getPrice(string memory symbol, uint256 decimals) internal view returns (uint256) {\n FeedRegistryInterface feedRegistry;\n\n if (sidRegistryAddress != address(0)) {\n // If sidRegistryAddress is available, fetch feedRegistryAddress from sidRegistry\n feedRegistry = FeedRegistryInterface(getFeedRegistryAddress());\n } else {\n // Use feedRegistry directly if sidRegistryAddress is not available\n feedRegistry = FeedRegistryInterface(feedRegistryAddress);\n }\n\n (, int256 answer, , uint256 updatedAt, ) = feedRegistry.latestRoundDataByName(symbol, \"USD\");\n if (answer <= 0) revert(\"invalid binance oracle price\");\n if (block.timestamp < updatedAt) revert(\"updatedAt exceeds block time\");\n\n uint256 deltaTime;\n unchecked {\n deltaTime = block.timestamp - updatedAt;\n }\n if (deltaTime > maxStalePeriod[symbol]) revert(\"binance oracle price expired\");\n\n uint256 decimalDelta = feedRegistry.decimalsByName(symbol, \"USD\");\n return (uint256(answer) * (10 ** (18 - decimalDelta))) * (10 ** (18 - decimals));\n }\n}\n" + }, + "contracts/oracles/BNBxOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IStaderStakeManager } from \"../interfaces/IStaderStakeManager.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\nimport { CorrelatedTokenOracle } from \"./common/CorrelatedTokenOracle.sol\";\n\n/**\n * @title BNBxOracle\n * @author Venus\n * @notice This oracle fetches the price of BNBx asset\n */\ncontract BNBxOracle is CorrelatedTokenOracle {\n /// @notice This is used as token address of BNB on BSC\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Address of StakeManager\n IStaderStakeManager public immutable STAKE_MANAGER;\n\n /// @notice Constructor for the implementation contract.\n constructor(\n address stakeManager,\n address bnbx,\n address resilientOracle,\n uint256 annualGrowthRate,\n uint256 _snapshotInterval,\n uint256 initialSnapshotMaxExchangeRate,\n uint256 initialSnapshotTimestamp,\n address accessControlManager,\n uint256 _snapshotGap\n )\n CorrelatedTokenOracle(\n bnbx,\n NATIVE_TOKEN_ADDR,\n resilientOracle,\n annualGrowthRate,\n _snapshotInterval,\n initialSnapshotMaxExchangeRate,\n initialSnapshotTimestamp,\n accessControlManager,\n _snapshotGap\n )\n {\n ensureNonzeroAddress(stakeManager);\n STAKE_MANAGER = IStaderStakeManager(stakeManager);\n }\n\n /**\n * @notice Fetches the amount of BNB for 1 BNBx\n * @return price The amount of BNB for BNBx\n */\n function getUnderlyingAmount() public view override returns (uint256) {\n return STAKE_MANAGER.convertBnbXToBnb(EXP_SCALE);\n }\n}\n" + }, + "contracts/oracles/BoundValidator.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"../interfaces/VBep20Interface.sol\";\nimport \"../interfaces/OracleInterface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\n/**\n * @title BoundValidator\n * @author Venus\n * @notice The BoundValidator contract is used to validate prices fetched from two different sources.\n * Each asset has an upper and lower bound ratio set in the config. In order for a price to be valid\n * it must fall within this range of the validator price.\n */\ncontract BoundValidator is AccessControlledV8, BoundValidatorInterface {\n struct ValidateConfig {\n /// @notice asset address\n address asset;\n /// @notice Upper bound of deviation between reported price and anchor price,\n /// beyond which the reported price will be invalidated\n uint256 upperBoundRatio;\n /// @notice Lower bound of deviation between reported price and anchor price,\n /// below which the reported price will be invalidated\n uint256 lowerBoundRatio;\n }\n\n /// @notice validation configs by asset\n mapping(address => ValidateConfig) public validateConfigs;\n\n /// @notice Emit this event when new validation configs are added\n event ValidateConfigAdded(address indexed asset, uint256 indexed upperBound, uint256 indexed lowerBound);\n\n /// @notice Constructor for the implementation contract. Sets immutable variables.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the owner of the contract\n * @param accessControlManager_ Address of the access control manager contract\n */\n function initialize(address accessControlManager_) external initializer {\n __AccessControlled_init(accessControlManager_);\n }\n\n /**\n * @notice Add multiple validation configs at the same time\n * @param configs Array of validation configs\n * @custom:access Only Governance\n * @custom:error Zero length error is thrown if length of the config array is 0\n * @custom:event Emits ValidateConfigAdded for each validation config that is successfully set\n */\n function setValidateConfigs(ValidateConfig[] memory configs) external {\n uint256 length = configs.length;\n if (length == 0) revert(\"invalid validate config length\");\n for (uint256 i; i < length; ++i) {\n setValidateConfig(configs[i]);\n }\n }\n\n /**\n * @notice Add a single validation config\n * @param config Validation config struct\n * @custom:access Only Governance\n * @custom:error Null address error is thrown if asset address is null\n * @custom:error Range error thrown if bound ratio is not positive\n * @custom:error Range error thrown if lower bound is greater than or equal to upper bound\n * @custom:event Emits ValidateConfigAdded when a validation config is successfully set\n */\n function setValidateConfig(ValidateConfig memory config) public {\n _checkAccessAllowed(\"setValidateConfig(ValidateConfig)\");\n\n if (config.asset == address(0)) revert(\"asset can't be zero address\");\n if (config.upperBoundRatio == 0 || config.lowerBoundRatio == 0) revert(\"bound must be positive\");\n if (config.upperBoundRatio <= config.lowerBoundRatio) revert(\"upper bound must be higher than lowner bound\");\n validateConfigs[config.asset] = config;\n emit ValidateConfigAdded(config.asset, config.upperBoundRatio, config.lowerBoundRatio);\n }\n\n /**\n * @notice Test reported asset price against anchor price\n * @param asset asset address\n * @param reportedPrice The price to be tested\n * @custom:error Missing error thrown if asset config is not set\n * @custom:error Price error thrown if anchor price is not valid\n */\n function validatePriceWithAnchorPrice(\n address asset,\n uint256 reportedPrice,\n uint256 anchorPrice\n ) public view virtual override returns (bool) {\n if (validateConfigs[asset].upperBoundRatio == 0) revert(\"validation config not exist\");\n if (anchorPrice == 0) revert(\"anchor price is not valid\");\n return _isWithinAnchor(asset, reportedPrice, anchorPrice);\n }\n\n /**\n * @notice Test whether the reported price is within the valid bounds\n * @param asset Asset address\n * @param reportedPrice The price to be tested\n * @param anchorPrice The reported price must be within the the valid bounds of this price\n */\n function _isWithinAnchor(address asset, uint256 reportedPrice, uint256 anchorPrice) private view returns (bool) {\n if (reportedPrice != 0) {\n // we need to multiply anchorPrice by 1e18 to make the ratio 18 decimals\n uint256 anchorRatio = (anchorPrice * 1e18) / reportedPrice;\n uint256 upperBoundAnchorRatio = validateConfigs[asset].upperBoundRatio;\n uint256 lowerBoundAnchorRatio = validateConfigs[asset].lowerBoundRatio;\n return anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio;\n }\n return false;\n }\n\n // BoundValidator is to get inherited, so it's a good practice to add some storage gaps like\n // OpenZepplin proposed in their contracts: https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n // solhint-disable-next-line\n uint256[49] private __gap;\n}\n" + }, + "contracts/oracles/ChainlinkOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"../interfaces/VBep20Interface.sol\";\nimport \"../interfaces/OracleInterface.sol\";\nimport \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\n/**\n * @title ChainlinkOracle\n * @author Venus\n * @notice This oracle fetches prices of assets from the Chainlink oracle.\n */\ncontract ChainlinkOracle is AccessControlledV8, OracleInterface {\n struct TokenConfig {\n /// @notice Underlying token address, which can't be a null address\n /// @notice Used to check if a token is supported\n /// @notice 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB address for native tokens\n /// (e.g BNB for BNB chain, ETH for Ethereum network)\n address asset;\n /// @notice Chainlink feed address\n address feed;\n /// @notice Price expiration period of this asset\n uint256 maxStalePeriod;\n }\n\n /// @notice Set this as asset address for native token on each chain.\n /// This is the underlying address for vBNB on BNB chain or an underlying asset for a native market on any chain.\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Manually set an override price, useful under extenuating conditions such as price feed failure\n mapping(address => uint256) public prices;\n\n /// @notice Token config by assets\n mapping(address => TokenConfig) public tokenConfigs;\n\n /// @notice Emit when a price is manually set\n event PricePosted(address indexed asset, uint256 previousPriceMantissa, uint256 newPriceMantissa);\n\n /// @notice Emit when a token config is added\n event TokenConfigAdded(address indexed asset, address feed, uint256 maxStalePeriod);\n\n modifier notNullAddress(address someone) {\n if (someone == address(0)) revert(\"can't be zero address\");\n _;\n }\n\n /// @notice Constructor for the implementation contract.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the owner of the contract\n * @param accessControlManager_ Address of the access control manager contract\n */\n function initialize(address accessControlManager_) external initializer {\n __AccessControlled_init(accessControlManager_);\n }\n\n /**\n * @notice Manually set the price of a given asset\n * @param asset Asset address\n * @param price Asset price in 18 decimals\n * @custom:access Only Governance\n * @custom:event Emits PricePosted event on successfully setup of asset price\n */\n function setDirectPrice(address asset, uint256 price) external notNullAddress(asset) {\n _checkAccessAllowed(\"setDirectPrice(address,uint256)\");\n\n uint256 previousPriceMantissa = prices[asset];\n prices[asset] = price;\n emit PricePosted(asset, previousPriceMantissa, price);\n }\n\n /**\n * @notice Add multiple token configs at the same time\n * @param tokenConfigs_ config array\n * @custom:access Only Governance\n * @custom:error Zero length error thrown, if length of the array in parameter is 0\n */\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\n if (tokenConfigs_.length == 0) revert(\"length can't be 0\");\n uint256 numTokenConfigs = tokenConfigs_.length;\n for (uint256 i; i < numTokenConfigs; ++i) {\n setTokenConfig(tokenConfigs_[i]);\n }\n }\n\n /**\n * @notice Add single token config. asset & feed cannot be null addresses and maxStalePeriod must be positive\n * @param tokenConfig Token config struct\n * @custom:access Only Governance\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error NotNullAddress error is thrown if token feed address is null\n * @custom:error Range error is thrown if maxStale period of token is not greater than zero\n * @custom:event Emits TokenConfigAdded event on successfully setting of the token config\n */\n function setTokenConfig(\n TokenConfig memory tokenConfig\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.feed) {\n _checkAccessAllowed(\"setTokenConfig(TokenConfig)\");\n\n if (tokenConfig.maxStalePeriod == 0) revert(\"stale period can't be zero\");\n tokenConfigs[tokenConfig.asset] = tokenConfig;\n emit TokenConfigAdded(tokenConfig.asset, tokenConfig.feed, tokenConfig.maxStalePeriod);\n }\n\n /**\n * @notice Gets the price of a asset from the chainlink oracle\n * @param asset Address of the asset\n * @return Price in USD from Chainlink or a manually set price for the asset\n */\n function getPrice(address asset) public view virtual returns (uint256) {\n uint256 decimals;\n\n if (asset == NATIVE_TOKEN_ADDR) {\n decimals = 18;\n } else {\n IERC20Metadata token = IERC20Metadata(asset);\n decimals = token.decimals();\n }\n\n return _getPriceInternal(asset, decimals);\n }\n\n /**\n * @notice Gets the Chainlink price for a given asset\n * @param asset address of the asset\n * @param decimals decimals of the asset\n * @return price Asset price in USD or a manually set price of the asset\n */\n function _getPriceInternal(address asset, uint256 decimals) internal view returns (uint256 price) {\n uint256 tokenPrice = prices[asset];\n if (tokenPrice != 0) {\n price = tokenPrice;\n } else {\n price = _getChainlinkPrice(asset);\n }\n\n uint256 decimalDelta = 18 - decimals;\n return price * (10 ** decimalDelta);\n }\n\n /**\n * @notice Get the Chainlink price for an asset, revert if token config doesn't exist\n * @dev The precision of the price feed is used to ensure the returned price has 18 decimals of precision\n * @param asset Address of the asset\n * @return price Price in USD, with 18 decimals of precision\n * @custom:error NotNullAddress error is thrown if the asset address is null\n * @custom:error Price error is thrown if the Chainlink price of asset is not greater than zero\n * @custom:error Timing error is thrown if current timestamp is less than the last updatedAt timestamp\n * @custom:error Timing error is thrown if time difference between current time and last updated time\n * is greater than maxStalePeriod\n */\n function _getChainlinkPrice(\n address asset\n ) private view notNullAddress(tokenConfigs[asset].asset) returns (uint256) {\n TokenConfig memory tokenConfig = tokenConfigs[asset];\n AggregatorV3Interface feed = AggregatorV3Interface(tokenConfig.feed);\n\n // note: maxStalePeriod cannot be 0\n uint256 maxStalePeriod = tokenConfig.maxStalePeriod;\n\n // Chainlink USD-denominated feeds store answers at 8 decimals, mostly\n uint256 decimalDelta = 18 - feed.decimals();\n\n (, int256 answer, , uint256 updatedAt, ) = feed.latestRoundData();\n if (answer <= 0) revert(\"chainlink price must be positive\");\n if (block.timestamp < updatedAt) revert(\"updatedAt exceeds block time\");\n\n uint256 deltaTime;\n unchecked {\n deltaTime = block.timestamp - updatedAt;\n }\n\n if (deltaTime > maxStalePeriod) revert(\"chainlink price expired\");\n\n return uint256(answer) * (10 ** decimalDelta);\n }\n}\n" + }, + "contracts/oracles/common/CorrelatedTokenOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { OracleInterface, ResilientOracleInterface } from \"../../interfaces/OracleInterface.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { SECONDS_PER_YEAR } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { ICappedOracle } from \"../../interfaces/ICappedOracle.sol\";\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\n\n/**\n * @title CorrelatedTokenOracle\n * @notice This oracle fetches the price of a token that is correlated to another token.\n */\nabstract contract CorrelatedTokenOracle is OracleInterface, ICappedOracle {\n /// @notice Address of the correlated token\n address public immutable CORRELATED_TOKEN;\n\n /// @notice Address of the underlying token\n address public immutable UNDERLYING_TOKEN;\n\n /// @notice Address of Resilient Oracle\n ResilientOracleInterface public immutable RESILIENT_ORACLE;\n\n /// @notice Address of the AccessControlManager contract\n IAccessControlManagerV8 public immutable ACCESS_CONTROL_MANAGER;\n\n //// @notice Growth rate percentage in seconds. Ex: 1e18 is 100%\n uint256 public growthRatePerSecond;\n\n /// @notice Snapshot update interval\n uint256 public snapshotInterval;\n\n /// @notice Last stored snapshot maximum exchange rate\n uint256 public snapshotMaxExchangeRate;\n\n /// @notice Last stored snapshot timestamp\n uint256 public snapshotTimestamp;\n\n /// @notice Gap to add when updating the snapshot\n uint256 public snapshotGap;\n\n /// @notice Emitted when the snapshot is updated\n event SnapshotUpdated(uint256 indexed maxExchangeRate, uint256 indexed timestamp);\n\n /// @notice Emitted when the growth rate is updated\n event GrowthRateUpdated(\n uint256 indexed oldGrowthRatePerSecond,\n uint256 indexed newGrowthRatePerSecond,\n uint256 indexed oldSnapshotInterval,\n uint256 newSnapshotInterval\n );\n\n /// @notice Emitted when the snapshot gap is updated\n event SnapshotGapUpdated(uint256 indexed oldSnapshotGap, uint256 indexed newSnapshotGap);\n\n /// @notice Thrown if the token address is invalid\n error InvalidTokenAddress();\n\n /// @notice Thrown if the growth rate is invalid\n error InvalidGrowthRate();\n\n /// @notice Thrown if the initial snapshot is invalid\n error InvalidInitialSnapshot();\n\n /// @notice Thrown if the max snapshot exchange rate is invalid\n error InvalidSnapshotMaxExchangeRate();\n\n /// @notice @notice Thrown when the action is prohibited by AccessControlManager\n error Unauthorized(address sender, address calledContract, string methodSignature);\n\n /**\n * @notice Constructor for the implementation contract.\n * @custom:error InvalidGrowthRate error is thrown if the growth rate is invalid\n * @custom:error InvalidInitialSnapshot error is thrown if the initial snapshot values are invalid\n */\n constructor(\n address _correlatedToken,\n address _underlyingToken,\n address _resilientOracle,\n uint256 _annualGrowthRate,\n uint256 _snapshotInterval,\n uint256 _initialSnapshotMaxExchangeRate,\n uint256 _initialSnapshotTimestamp,\n address _accessControlManager,\n uint256 _snapshotGap\n ) {\n growthRatePerSecond = _annualGrowthRate / SECONDS_PER_YEAR;\n\n if ((growthRatePerSecond == 0 && _snapshotInterval > 0) || (growthRatePerSecond > 0 && _snapshotInterval == 0))\n revert InvalidGrowthRate();\n\n if ((_initialSnapshotMaxExchangeRate == 0 || _initialSnapshotTimestamp == 0) && _snapshotInterval > 0) {\n revert InvalidInitialSnapshot();\n }\n\n ensureNonzeroAddress(_correlatedToken);\n ensureNonzeroAddress(_underlyingToken);\n ensureNonzeroAddress(_resilientOracle);\n ensureNonzeroAddress(_accessControlManager);\n\n CORRELATED_TOKEN = _correlatedToken;\n UNDERLYING_TOKEN = _underlyingToken;\n RESILIENT_ORACLE = ResilientOracleInterface(_resilientOracle);\n snapshotInterval = _snapshotInterval;\n\n snapshotMaxExchangeRate = _initialSnapshotMaxExchangeRate;\n snapshotTimestamp = _initialSnapshotTimestamp;\n snapshotGap = _snapshotGap;\n\n ACCESS_CONTROL_MANAGER = IAccessControlManagerV8(_accessControlManager);\n }\n\n /**\n * @notice Directly sets the snapshot exchange rate and timestamp\n * @param _snapshotMaxExchangeRate The exchange rate to set\n * @param _snapshotTimestamp The timestamp to set\n * @custom:event Emits SnapshotUpdated event on successful update of the snapshot\n */\n function setSnapshot(uint256 _snapshotMaxExchangeRate, uint256 _snapshotTimestamp) external {\n _checkAccessAllowed(\"setSnapshot(uint256,uint256)\");\n\n snapshotMaxExchangeRate = _snapshotMaxExchangeRate;\n snapshotTimestamp = _snapshotTimestamp;\n\n emit SnapshotUpdated(snapshotMaxExchangeRate, snapshotTimestamp);\n }\n\n /**\n * @notice Sets the growth rate and snapshot interval\n * @param _annualGrowthRate The annual growth rate to set\n * @param _snapshotInterval The snapshot interval to set\n * @custom:error InvalidGrowthRate error is thrown if the growth rate is invalid\n * @custom:event Emits GrowthRateUpdated event on successful update of the growth rate\n */\n function setGrowthRate(uint256 _annualGrowthRate, uint256 _snapshotInterval) external {\n _checkAccessAllowed(\"setGrowthRate(uint256,uint256)\");\n uint256 oldGrowthRatePerSecond = growthRatePerSecond;\n\n growthRatePerSecond = _annualGrowthRate / SECONDS_PER_YEAR;\n\n if ((growthRatePerSecond == 0 && _snapshotInterval > 0) || (growthRatePerSecond > 0 && _snapshotInterval == 0))\n revert InvalidGrowthRate();\n\n emit GrowthRateUpdated(oldGrowthRatePerSecond, growthRatePerSecond, snapshotInterval, _snapshotInterval);\n\n snapshotInterval = _snapshotInterval;\n }\n\n /**\n * @notice Sets the snapshot gap\n * @param _snapshotGap The snapshot gap to set\n * @custom:event Emits SnapshotGapUpdated event on successful update of the snapshot gap\n */\n function setSnapshotGap(uint256 _snapshotGap) external {\n _checkAccessAllowed(\"setSnapshotGap(uint256)\");\n\n emit SnapshotGapUpdated(snapshotGap, _snapshotGap);\n\n snapshotGap = _snapshotGap;\n }\n\n /**\n * @notice Returns if the price is capped\n * @return isCapped Boolean indicating if the price is capped\n */\n function isCapped() external view virtual returns (bool) {\n if (snapshotInterval == 0) {\n return false;\n }\n\n uint256 maxAllowedExchangeRate = getMaxAllowedExchangeRate();\n if (maxAllowedExchangeRate == 0) {\n return false;\n }\n\n uint256 exchangeRate = getUnderlyingAmount();\n\n return exchangeRate > maxAllowedExchangeRate;\n }\n\n /**\n * @notice Updates the snapshot price and timestamp\n * @custom:event Emits SnapshotUpdated event on successful update of the snapshot\n * @custom:error InvalidSnapshotMaxExchangeRate error is thrown if the max snapshot exchange rate is zero\n */\n function updateSnapshot() public override {\n if (block.timestamp - snapshotTimestamp < snapshotInterval || snapshotInterval == 0) return;\n\n uint256 exchangeRate = getUnderlyingAmount();\n uint256 maxAllowedExchangeRate = getMaxAllowedExchangeRate();\n\n snapshotMaxExchangeRate =\n (exchangeRate > maxAllowedExchangeRate ? maxAllowedExchangeRate : exchangeRate) +\n snapshotGap;\n snapshotTimestamp = block.timestamp;\n\n if (snapshotMaxExchangeRate == 0) revert InvalidSnapshotMaxExchangeRate();\n\n RESILIENT_ORACLE.updateAssetPrice(UNDERLYING_TOKEN);\n emit SnapshotUpdated(snapshotMaxExchangeRate, snapshotTimestamp);\n }\n\n /**\n * @notice Fetches the price of the token\n * @param asset Address of the token\n * @return price The price of the token in scaled decimal places. It can be capped\n * to a maximum value taking into account the growth rate\n * @custom:error InvalidTokenAddress error is thrown if the token address is invalid\n */\n function getPrice(address asset) public view override returns (uint256) {\n if (asset != CORRELATED_TOKEN) revert InvalidTokenAddress();\n\n uint256 exchangeRate = getUnderlyingAmount();\n\n if (snapshotInterval == 0) {\n return _calculatePrice(exchangeRate);\n }\n\n uint256 maxAllowedExchangeRate = getMaxAllowedExchangeRate();\n\n uint256 finalExchangeRate = (exchangeRate > maxAllowedExchangeRate && maxAllowedExchangeRate != 0)\n ? maxAllowedExchangeRate\n : exchangeRate;\n\n return _calculatePrice(finalExchangeRate);\n }\n\n /**\n * @notice Gets the maximum allowed exchange rate for token\n * @return maxExchangeRate Maximum allowed exchange rate\n */\n function getMaxAllowedExchangeRate() public view returns (uint256) {\n uint256 timeElapsed = block.timestamp - snapshotTimestamp;\n uint256 maxExchangeRate = snapshotMaxExchangeRate +\n (snapshotMaxExchangeRate * growthRatePerSecond * timeElapsed) /\n 1e18;\n return maxExchangeRate;\n }\n\n /**\n * @notice Gets the underlying amount for correlated token\n * @return underlyingAmount Amount of underlying token\n */\n function getUnderlyingAmount() public view virtual returns (uint256);\n\n /**\n * @notice Fetches price of the token based on an underlying exchange rate\n * @param exchangeRate The underlying exchange rate to use\n * @return price The price of the token in scaled decimal places\n */\n function _calculatePrice(uint256 exchangeRate) internal view returns (uint256) {\n uint256 underlyingUSDPrice = RESILIENT_ORACLE.getPrice(UNDERLYING_TOKEN);\n\n IERC20Metadata token = IERC20Metadata(CORRELATED_TOKEN);\n uint256 decimals = token.decimals();\n\n return (exchangeRate * underlyingUSDPrice) / (10 ** decimals);\n }\n\n /**\n * @notice Reverts if the call is not allowed by AccessControlManager\n * @param signature Method signature\n * @custom:error Unauthorized error is thrown if the call is not allowed\n */\n function _checkAccessAllowed(string memory signature) internal view {\n bool isAllowedToCall = ACCESS_CONTROL_MANAGER.isAllowedToCall(msg.sender, signature);\n\n if (!isAllowedToCall) {\n revert Unauthorized(msg.sender, address(this), signature);\n }\n }\n}\n" + }, + "contracts/oracles/ERC4626Oracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC4626 } from \"../interfaces/IERC4626.sol\";\nimport { CorrelatedTokenOracle } from \"./common/CorrelatedTokenOracle.sol\";\n\n/**\n * @title ERC4626Oracle\n * @author Venus\n * @notice This oracle fetches the price of ERC4626 tokens\n */\ncontract ERC4626Oracle is CorrelatedTokenOracle {\n uint256 public immutable ONE_CORRELATED_TOKEN;\n\n /// @notice Constructor for the implementation contract.\n constructor(\n address correlatedToken,\n address underlyingToken,\n address resilientOracle,\n uint256 annualGrowthRate,\n uint256 _snapshotInterval,\n uint256 initialSnapshotMaxExchangeRate,\n uint256 initialSnapshotTimestamp,\n address accessControlManager,\n uint256 _snapshotGap\n )\n CorrelatedTokenOracle(\n correlatedToken,\n underlyingToken,\n resilientOracle,\n annualGrowthRate,\n _snapshotInterval,\n initialSnapshotMaxExchangeRate,\n initialSnapshotTimestamp,\n accessControlManager,\n _snapshotGap\n )\n {\n ONE_CORRELATED_TOKEN = 10 ** IERC4626(correlatedToken).decimals();\n }\n\n /**\n * @notice Fetches the amount of underlying token for 1 correlated token\n * @return amount The amount of underlying token for correlated token\n */\n function getUnderlyingAmount() public view override returns (uint256) {\n return IERC4626(CORRELATED_TOKEN).convertToAssets(ONE_CORRELATED_TOKEN);\n }\n}\n" + }, + "contracts/oracles/EtherfiAccountantOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { CorrelatedTokenOracle } from \"./common/CorrelatedTokenOracle.sol\";\nimport { IAccountant } from \"../interfaces/IAccountant.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\n/**\n * @title EtherfiAccountantOracle\n * @author Venus\n * @notice This oracle fetches the price of any Ether.fi asset that uses\n * Accountant contracts to derive the underlying price\n */\ncontract EtherfiAccountantOracle is CorrelatedTokenOracle {\n /// @notice Address of Accountant\n IAccountant public immutable ACCOUNTANT;\n\n /// @notice Constructor for the implementation contract.\n constructor(\n address accountant,\n address correlatedToken,\n address underlyingToken,\n address resilientOracle,\n uint256 annualGrowthRate,\n uint256 _snapshotInterval,\n uint256 initialSnapshotMaxExchangeRate,\n uint256 initialSnapshotTimestamp,\n address accessControlManager,\n uint256 _snapshotGap\n )\n CorrelatedTokenOracle(\n correlatedToken,\n underlyingToken,\n resilientOracle,\n annualGrowthRate,\n _snapshotInterval,\n initialSnapshotMaxExchangeRate,\n initialSnapshotTimestamp,\n accessControlManager,\n _snapshotGap\n )\n {\n ensureNonzeroAddress(accountant);\n ACCOUNTANT = IAccountant(accountant);\n }\n\n /**\n * @notice Fetches the conversion rate from the ACCOUNTANT contract\n * @return amount Amount of WBTC\n */\n function getUnderlyingAmount() public view override returns (uint256) {\n return ACCOUNTANT.getRateSafe();\n }\n}\n" + }, + "contracts/oracles/mocks/MockAccountant.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"../../interfaces/IAccountant.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract MockAccountant is IAccountant, Ownable {\n uint256 public rate;\n\n constructor() Ownable() {}\n\n function setRate(uint256 _rate) external onlyOwner {\n rate = _rate;\n }\n\n function getRateSafe() external view override returns (uint256) {\n return rate;\n }\n}\n" + }, + "contracts/oracles/mocks/MockBinanceFeedRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"../../interfaces/FeedRegistryInterface.sol\";\n\ncontract MockBinanceFeedRegistry is FeedRegistryInterface {\n mapping(string => uint256) public assetPrices;\n\n function setAssetPrice(string memory base, uint256 price) external {\n assetPrices[base] = price;\n }\n\n function latestRoundDataByName(\n string memory base,\n string memory quote\n )\n external\n view\n override\n returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)\n {\n quote;\n return (0, int256(assetPrices[base]), 0, block.timestamp - 10, 0);\n }\n\n function decimalsByName(string memory base, string memory quote) external view override returns (uint8) {\n return 8;\n }\n}\n" + }, + "contracts/oracles/mocks/MockBinanceOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { OwnableUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { OracleInterface } from \"../../interfaces/OracleInterface.sol\";\n\ncontract MockBinanceOracle is OwnableUpgradeable, OracleInterface {\n mapping(address => uint256) public assetPrices;\n\n constructor() {}\n\n function initialize() public initializer {}\n\n function setPrice(address asset, uint256 price) external {\n assetPrices[asset] = price;\n }\n\n function getPrice(address token) public view returns (uint256) {\n return assetPrices[token];\n }\n}\n" + }, + "contracts/oracles/mocks/MockChainlinkOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { OwnableUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { OracleInterface } from \"../../interfaces/OracleInterface.sol\";\n\ncontract MockChainlinkOracle is OwnableUpgradeable, OracleInterface {\n mapping(address => uint256) public assetPrices;\n\n //set price in 6 decimal precision\n constructor() {}\n\n function initialize() public initializer {\n __Ownable_init();\n }\n\n function setPrice(address asset, uint256 price) external {\n assetPrices[asset] = price;\n }\n\n //https://compound.finance/docs/prices\n function getPrice(address token) public view returns (uint256) {\n return assetPrices[token];\n }\n}\n" + }, + "contracts/oracles/mocks/MockPendlePtOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"../../interfaces/IPendlePtOracle.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract MockPendlePtOracle is IPendlePtOracle, Ownable {\n mapping(address => mapping(uint32 => uint256)) public ptToAssetRate;\n mapping(address => mapping(uint32 => uint256)) public ptToSyRate;\n\n constructor() Ownable() {}\n\n function setPtToAssetRate(address market, uint32 duration, uint256 rate) external onlyOwner {\n ptToAssetRate[market][duration] = rate;\n }\n\n function setPtToSyRate(address market, uint32 duration, uint256 rate) external onlyOwner {\n ptToSyRate[market][duration] = rate;\n }\n\n function getPtToAssetRate(address market, uint32 duration) external view returns (uint256) {\n return ptToAssetRate[market][duration];\n }\n\n function getPtToSyRate(address market, uint32 duration) external view returns (uint256) {\n return ptToSyRate[market][duration];\n }\n\n function getOracleState(\n address /* market */,\n uint32 /* duration */\n )\n external\n pure\n returns (bool increaseCardinalityRequired, uint16 cardinalityRequired, bool oldestObservationSatisfied)\n {\n return (false, 0, true);\n }\n}\n" + }, + "contracts/oracles/mocks/MockSFrxEthFraxOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"../../interfaces/ISfrxEthFraxOracle.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract MockSfrxEthFraxOracle is ISfrxEthFraxOracle, Ownable {\n bool public isBadData;\n uint256 public priceLow;\n uint256 public priceHigh;\n\n constructor() Ownable() {}\n\n function setPrices(bool _isBadData, uint256 _priceLow, uint256 _priceHigh) external onlyOwner {\n isBadData = _isBadData;\n priceLow = _priceLow;\n priceHigh = _priceHigh;\n }\n\n function getPrices() external view override returns (bool, uint256, uint256) {\n return (isBadData, priceLow, priceHigh);\n }\n}\n" + }, + "contracts/oracles/OneJumpOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { CorrelatedTokenOracle } from \"./common/CorrelatedTokenOracle.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { OracleInterface } from \"../interfaces/OracleInterface.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\n/**\n * @title OneJumpOracle\n * @author Venus\n * @notice This oracle fetches the price of an asset in through an intermediate asset\n */\ncontract OneJumpOracle is CorrelatedTokenOracle {\n /// @notice Address of the intermediate oracle\n OracleInterface public immutable INTERMEDIATE_ORACLE;\n\n /// @notice Constructor for the implementation contract.\n constructor(\n address correlatedToken,\n address underlyingToken,\n address resilientOracle,\n address intermediateOracle,\n uint256 annualGrowthRate,\n uint256 _snapshotInterval,\n uint256 initialSnapshotMaxExchangeRate,\n uint256 initialSnapshotTimestamp,\n address accessControlManager,\n uint256 _snapshotGap\n )\n CorrelatedTokenOracle(\n correlatedToken,\n underlyingToken,\n resilientOracle,\n annualGrowthRate,\n _snapshotInterval,\n initialSnapshotMaxExchangeRate,\n initialSnapshotTimestamp,\n accessControlManager,\n _snapshotGap\n )\n {\n ensureNonzeroAddress(intermediateOracle);\n INTERMEDIATE_ORACLE = OracleInterface(intermediateOracle);\n }\n\n /**\n * @notice Fetches the amount of the underlying token for 1 correlated token, using the intermediate oracle\n * @return amount The amount of the underlying token for 1 correlated token scaled by the underlying token decimals\n */\n function getUnderlyingAmount() public view override returns (uint256) {\n uint256 underlyingDecimals = IERC20Metadata(UNDERLYING_TOKEN).decimals();\n uint256 correlatedDecimals = IERC20Metadata(CORRELATED_TOKEN).decimals();\n\n uint256 underlyingAmount = INTERMEDIATE_ORACLE.getPrice(CORRELATED_TOKEN);\n\n return (underlyingAmount * (10 ** correlatedDecimals)) / (10 ** (36 - underlyingDecimals));\n }\n}\n" + }, + "contracts/oracles/PendleOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IPendlePtOracle } from \"../interfaces/IPendlePtOracle.sol\";\nimport { CorrelatedTokenOracle } from \"./common/CorrelatedTokenOracle.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\n/**\n * @title PendleOracle\n * @author Venus\n * @notice This oracle fetches the price of a pendle token\n * @dev As a base price the oracle uses either the price of the Pendle\n * market's asset (in this case PT_TO_ASSET rate should be used) or\n * the price of the Pendle market's interest bearing token (e.g. wstETH\n * for stETH; in this case PT_TO_SY rate should be used). Technically,\n * interest bearing token is different from standardized yield (SY) token,\n * but since SY is a wrapper around an interest bearing token, we can safely\n * assume the prices of the two are equal. This is not always true for asset\n * price though: using PT_TO_ASSET rate assumes that the yield token can\n * be seamlessly redeemed for the underlying asset. In reality, this might\n * not always be the case. For more details, see\n * https://docs.pendle.finance/Developers/Contracts/StandardizedYield\n */\ncontract PendleOracle is CorrelatedTokenOracle {\n struct ConstructorParams {\n /// @notice Pendle market\n address market;\n /// @notice Pendle oracle\n address ptOracle;\n /// @notice Either PT_TO_ASSET or PT_TO_SY\n RateKind rateKind;\n /// @notice Pendle PT token\n address ptToken;\n /// @notice Underlying token, can be either the market's asset or the interest bearing token\n address underlyingToken;\n /// @notice Resilient oracle to get the underlying token price from\n address resilientOracle;\n /// @notice TWAP duration to call Pendle oracle with\n uint32 twapDuration;\n /// @notice Annual growth rate of the underlying token\n uint256 annualGrowthRate;\n /// @notice Snapshot interval for the oracle\n uint256 snapshotInterval;\n /// @notice Initial exchange rate of the underlying token\n uint256 initialSnapshotMaxExchangeRate;\n /// @notice Initial timestamp of the underlying token\n uint256 initialSnapshotTimestamp;\n /// @notice Access control manager\n address accessControlManager;\n /// @notice Gap to add when updating the snapshot\n uint256 snapshotGap;\n }\n\n /// @notice Which asset to use as a base for the returned PT\n /// price. Can be either a standardized yield token (SY), in\n /// this case PT/SY price is returned, or the Pendle\n /// market's asset directly.\n enum RateKind {\n PT_TO_ASSET,\n PT_TO_SY\n }\n\n /// @notice Address of the PT oracle\n IPendlePtOracle public immutable PT_ORACLE;\n\n /// @notice Whether to use PT/SY (standardized yield token) rate\n /// or PT/market asset rate\n RateKind public immutable RATE_KIND;\n\n /// @notice Address of the market\n address public immutable MARKET;\n\n /// @notice Twap duration for the oracle\n uint32 public immutable TWAP_DURATION;\n\n /// @notice Decimals of the underlying token\n /// @dev We make an assumption that the underlying decimals will\n /// not change throughout the lifetime of the Pendle market\n uint8 public immutable UNDERLYING_DECIMALS;\n\n /// @notice Thrown if the duration is invalid\n error InvalidDuration();\n\n /**\n * @notice Constructor for the implementation contract.\n * @custom:error InvalidDuration Thrown if the duration is invalid\n */\n constructor(\n ConstructorParams memory params\n )\n CorrelatedTokenOracle(\n params.ptToken,\n params.underlyingToken,\n params.resilientOracle,\n params.annualGrowthRate,\n params.snapshotInterval,\n params.initialSnapshotMaxExchangeRate,\n params.initialSnapshotTimestamp,\n params.accessControlManager,\n params.snapshotGap\n )\n {\n ensureNonzeroAddress(params.market);\n ensureNonzeroAddress(params.ptOracle);\n ensureNonzeroValue(params.twapDuration);\n\n MARKET = params.market;\n PT_ORACLE = IPendlePtOracle(params.ptOracle);\n RATE_KIND = params.rateKind;\n TWAP_DURATION = params.twapDuration;\n UNDERLYING_DECIMALS = IERC20Metadata(UNDERLYING_TOKEN).decimals();\n\n (bool increaseCardinalityRequired, , bool oldestObservationSatisfied) = PT_ORACLE.getOracleState(\n MARKET,\n TWAP_DURATION\n );\n if (increaseCardinalityRequired || !oldestObservationSatisfied) {\n revert InvalidDuration();\n }\n }\n\n /// @notice Fetches the amount of underlying token for 1 PT\n /// @return amount The amount of underlying token (either the market's asset\n /// or the yield token) for 1 PT, adjusted for decimals such that the result\n /// has the same precision as the underlying token\n function getUnderlyingAmount() public view override returns (uint256) {\n uint256 rate;\n if (RATE_KIND == RateKind.PT_TO_SY) {\n rate = PT_ORACLE.getPtToSyRate(MARKET, TWAP_DURATION);\n } else {\n rate = PT_ORACLE.getPtToAssetRate(MARKET, TWAP_DURATION);\n }\n return ((10 ** UNDERLYING_DECIMALS) * rate) / 1e18;\n }\n}\n" + }, + "contracts/oracles/SequencerChainlinkOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.25;\n\nimport { ChainlinkOracle } from \"./ChainlinkOracle.sol\";\nimport { AggregatorV3Interface } from \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\n\n/**\n @title Sequencer Chain Link Oracle\n @notice Oracle to fetch price using chainlink oracles on L2s with sequencer\n*/\ncontract SequencerChainlinkOracle is ChainlinkOracle {\n /// @notice L2 Sequencer feed\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n AggregatorV3Interface public immutable sequencer;\n\n /// @notice L2 Sequencer grace period\n uint256 public constant GRACE_PERIOD_TIME = 3600;\n\n /**\n @notice Contract constructor\n @param _sequencer L2 sequencer\n @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(AggregatorV3Interface _sequencer) ChainlinkOracle() {\n require(address(_sequencer) != address(0), \"zero address\");\n\n sequencer = _sequencer;\n }\n\n /// @inheritdoc ChainlinkOracle\n function getPrice(address asset) public view override returns (uint) {\n if (!isSequencerActive()) revert(\"L2 sequencer unavailable\");\n return super.getPrice(asset);\n }\n\n function isSequencerActive() internal view returns (bool) {\n // answer from oracle is a variable with a value of either 1 or 0\n // 0: The sequencer is up\n // 1: The sequencer is down\n // startedAt: This timestamp indicates when the sequencer changed status\n (, int256 answer, uint256 startedAt, , ) = sequencer.latestRoundData();\n if (block.timestamp - startedAt <= GRACE_PERIOD_TIME || answer == 1) return false;\n return true;\n }\n}\n" + }, + "contracts/oracles/SFraxOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ISFrax } from \"../interfaces/ISFrax.sol\";\nimport { CorrelatedTokenOracle } from \"./common/CorrelatedTokenOracle.sol\";\nimport { EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\n\n/**\n * @title SFraxOracle\n * @author Venus\n * @notice This oracle fetches the price of sFrax\n */\ncontract SFraxOracle is CorrelatedTokenOracle {\n /// @notice Constructor for the implementation contract.\n constructor(\n address sFrax,\n address frax,\n address resilientOracle,\n uint256 annualGrowthRate,\n uint256 _snapshotInterval,\n uint256 initialSnapshotMaxExchangeRate,\n uint256 initialSnapshotTimestamp,\n address accessControlManager,\n uint256 _snapshotGap\n )\n CorrelatedTokenOracle(\n sFrax,\n frax,\n resilientOracle,\n annualGrowthRate,\n _snapshotInterval,\n initialSnapshotMaxExchangeRate,\n initialSnapshotTimestamp,\n accessControlManager,\n _snapshotGap\n )\n {}\n\n /**\n * @notice Fetches the amount of FRAX for 1 sFrax\n * @return amount The amount of FRAX for sFrax\n */\n function getUnderlyingAmount() public view override returns (uint256) {\n return ISFrax(CORRELATED_TOKEN).convertToAssets(EXP_SCALE);\n }\n}\n" + }, + "contracts/oracles/SFrxETHOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ISfrxEthFraxOracle } from \"../interfaces/ISfrxEthFraxOracle.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { OracleInterface } from \"../interfaces/OracleInterface.sol\";\n\n/**\n * @title SFrxETHOracle\n * @author Venus\n * @notice This oracle fetches the price of sfrxETH\n */\ncontract SFrxETHOracle is AccessControlledV8, OracleInterface {\n /// @notice Address of SfrxEthFraxOracle\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ISfrxEthFraxOracle public immutable SFRXETH_FRAX_ORACLE;\n\n /// @notice Address of sfrxETH\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable SFRXETH;\n\n /// @notice Maximum allowed price difference\n uint256 public maxAllowedPriceDifference;\n\n /// @notice Emits when the maximum allowed price difference is updated\n event MaxAllowedPriceDifferenceUpdated(uint256 oldMaxAllowedPriceDifference, uint256 newMaxAllowedPriceDifference);\n\n /// @notice Thrown if the price data is invalid\n error BadPriceData();\n\n /// @notice Thrown if the price difference exceeds the allowed limit\n error PriceDifferenceExceeded();\n\n /// @notice Thrown if the token address is invalid\n error InvalidTokenAddress();\n\n /// @notice Constructor for the implementation contract.\n /// @custom:oz-upgrades-unsafe-allow constructor\n /// @custom:error ZeroAddressNotAllowed is thrown when `_sfrxEthFraxOracle` or `_sfrxETH` are the zero address\n constructor(address _sfrxEthFraxOracle, address _sfrxETH) {\n ensureNonzeroAddress(_sfrxEthFraxOracle);\n ensureNonzeroAddress(_sfrxETH);\n\n SFRXETH_FRAX_ORACLE = ISfrxEthFraxOracle(_sfrxEthFraxOracle);\n SFRXETH = _sfrxETH;\n\n _disableInitializers();\n }\n\n /**\n * @notice Sets the contracts required to fetch prices\n * @param _acm Address of the access control manager contract\n * @param _maxAllowedPriceDifference Maximum allowed price difference\n * @custom:error ZeroValueNotAllowed is thrown if `_maxAllowedPriceDifference` is zero\n */\n function initialize(address _acm, uint256 _maxAllowedPriceDifference) external initializer {\n ensureNonzeroValue(_maxAllowedPriceDifference);\n\n __AccessControlled_init(_acm);\n maxAllowedPriceDifference = _maxAllowedPriceDifference;\n }\n\n /**\n * @notice Sets the maximum allowed price difference\n * @param _maxAllowedPriceDifference Maximum allowed price difference\n * @custom:error ZeroValueNotAllowed is thrown if `_maxAllowedPriceDifference` is zero\n */\n function setMaxAllowedPriceDifference(uint256 _maxAllowedPriceDifference) external {\n _checkAccessAllowed(\"setMaxAllowedPriceDifference(uint256)\");\n ensureNonzeroValue(_maxAllowedPriceDifference);\n\n emit MaxAllowedPriceDifferenceUpdated(maxAllowedPriceDifference, _maxAllowedPriceDifference);\n maxAllowedPriceDifference = _maxAllowedPriceDifference;\n }\n\n /**\n * @notice Fetches the USD price of sfrxETH\n * @param asset Address of the sfrxETH token\n * @return price The price scaled by 1e18\n * @custom:error InvalidTokenAddress is thrown when the `asset` is not the sfrxETH token (`SFRXETH`)\n * @custom:error BadPriceData is thrown if the `SFRXETH_FRAX_ORACLE` oracle informs it has bad data\n * @custom:error ZeroValueNotAllowed is thrown if the prices (low or high, in USD) are zero\n * @custom:error PriceDifferenceExceeded is thrown if priceHigh/priceLow is greater than `maxAllowedPriceDifference`\n */\n function getPrice(address asset) external view returns (uint256) {\n if (asset != SFRXETH) revert InvalidTokenAddress();\n\n (bool isBadData, uint256 priceLow, uint256 priceHigh) = SFRXETH_FRAX_ORACLE.getPrices();\n\n if (isBadData) revert BadPriceData();\n\n // calculate price in USD\n uint256 priceHighInUSD = (EXP_SCALE ** 2) / priceLow;\n uint256 priceLowInUSD = (EXP_SCALE ** 2) / priceHigh;\n\n ensureNonzeroValue(priceHighInUSD);\n ensureNonzeroValue(priceLowInUSD);\n\n // validate price difference\n uint256 difference = (priceHighInUSD * EXP_SCALE) / priceLowInUSD;\n if (difference > maxAllowedPriceDifference) revert PriceDifferenceExceeded();\n\n // calculate and return average price\n return (priceHighInUSD + priceLowInUSD) / 2;\n }\n}\n" + }, + "contracts/oracles/SlisBNBOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ISynclubStakeManager } from \"../interfaces/ISynclubStakeManager.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { CorrelatedTokenOracle } from \"./common/CorrelatedTokenOracle.sol\";\nimport { EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\n\n/**\n * @title SlisBNBOracle\n * @author Venus\n * @notice This oracle fetches the price of slisBNB asset\n */\ncontract SlisBNBOracle is CorrelatedTokenOracle {\n /// @notice This is used as token address of BNB on BSC\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Address of StakeManager\n ISynclubStakeManager public immutable STAKE_MANAGER;\n\n /// @notice Constructor for the implementation contract.\n constructor(\n address stakeManager,\n address slisBNB,\n address resilientOracle,\n uint256 annualGrowthRate,\n uint256 _snapshotInterval,\n uint256 initialSnapshotMaxExchangeRate,\n uint256 initialSnapshotTimestamp,\n address accessControlManager,\n uint256 _snapshotGap\n )\n CorrelatedTokenOracle(\n slisBNB,\n NATIVE_TOKEN_ADDR,\n resilientOracle,\n annualGrowthRate,\n _snapshotInterval,\n initialSnapshotMaxExchangeRate,\n initialSnapshotTimestamp,\n accessControlManager,\n _snapshotGap\n )\n {\n ensureNonzeroAddress(stakeManager);\n STAKE_MANAGER = ISynclubStakeManager(stakeManager);\n }\n\n /**\n * @notice Fetches the amount of BNB for 1 slisBNB\n * @return amount The amount of BNB for slisBNB\n */\n function getUnderlyingAmount() public view override returns (uint256) {\n return STAKE_MANAGER.convertSnBnbToBnb(EXP_SCALE);\n }\n}\n" + }, + "contracts/oracles/StableUsdtPriceFeed.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"../interfaces/OracleInterface.sol\";\n\n/**\n * @title StableUsdtPriceFeed\n * @dev This contract is used to get the price of USDT from a Resilient Oracle\n * and bounds the price to a certain range.\n */\ncontract StableUsdtPriceFeed {\n ResilientOracleInterface public resilientOracle;\n\n address public constant USDT_TOKEN_ADDR = 0x55d398326f99059fF775485246999027B3197955;\n uint256 public constant UPPER_BOUND = 1020000000000000000; // 1.02 USD\n uint256 public constant LOWER_BOUND = 980000000000000000; // 0.98 USD\n\n constructor(address _resilientOracle) {\n require(_resilientOracle != address(0), \"Zero address provided\");\n resilientOracle = ResilientOracleInterface(_resilientOracle);\n }\n\n function latestAnswer() external view returns (int256 answer) {\n // get price\n uint256 price = getPrice();\n // cast price to int256\n answer = int256(price);\n }\n\n function latestRoundData()\n external\n view\n returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)\n {\n // get price\n uint256 _answer = getPrice();\n // mock timestamp to latest block timestamp\n uint256 timestamp = block.timestamp;\n // mock roundId to timestamp\n roundId = uint80(timestamp);\n return (roundId, int256(_answer), timestamp, timestamp, roundId);\n }\n\n function decimals() external pure returns (uint8) {\n return 18;\n }\n\n function description() external pure returns (string memory) {\n return \"Stabilized USDT Price Feed\";\n }\n\n function version() external pure returns (uint256) {\n return 1;\n }\n\n /**\n * @dev Get the price from the Resilient Oracle, and bound it to the range\n * @return price The price of USDT in 18 decimals\n */\n function getPrice() private view returns (uint256 price) {\n // get USDT price (18 decimals)\n price = resilientOracle.getPrice(USDT_TOKEN_ADDR);\n price = price < LOWER_BOUND ? LOWER_BOUND : (price > UPPER_BOUND ? UPPER_BOUND : price);\n }\n}\n" + }, + "contracts/oracles/StkBNBOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IPStakePool } from \"../interfaces/IPStakePool.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\nimport { CorrelatedTokenOracle } from \"./common/CorrelatedTokenOracle.sol\";\n\n/**\n * @title StkBNBOracle\n * @author Venus\n * @notice This oracle fetches the price of stkBNB asset\n */\ncontract StkBNBOracle is CorrelatedTokenOracle {\n /// @notice This is used as token address of BNB on BSC\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Address of StakePool\n IPStakePool public immutable STAKE_POOL;\n\n /// @notice Thrown if the pool token supply is zero\n error PoolTokenSupplyIsZero();\n\n /// @notice Constructor for the implementation contract.\n constructor(\n address stakePool,\n address stkBNB,\n address resilientOracle,\n uint256 annualGrowthRate,\n uint256 _snapshotInterval,\n uint256 initialSnapshotMaxExchangeRate,\n uint256 initialSnapshotTimestamp,\n address accessControlManager,\n uint256 _snapshotGap\n )\n CorrelatedTokenOracle(\n stkBNB,\n NATIVE_TOKEN_ADDR,\n resilientOracle,\n annualGrowthRate,\n _snapshotInterval,\n initialSnapshotMaxExchangeRate,\n initialSnapshotTimestamp,\n accessControlManager,\n _snapshotGap\n )\n {\n ensureNonzeroAddress(stakePool);\n STAKE_POOL = IPStakePool(stakePool);\n }\n\n /**\n * @notice Fetches the amount of BNB for 1 stkBNB\n * @return price The amount of BNB for stkBNB\n * @custom:error PoolTokenSupplyIsZero error is thrown if the pool token supply is zero\n */\n function getUnderlyingAmount() public view override returns (uint256) {\n IPStakePool.Data memory exchangeRateData = STAKE_POOL.exchangeRate();\n\n if (exchangeRateData.poolTokenSupply == 0) {\n revert PoolTokenSupplyIsZero();\n }\n\n return (exchangeRateData.totalWei * EXP_SCALE) / exchangeRateData.poolTokenSupply;\n }\n}\n" + }, + "contracts/oracles/WBETHOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IWBETH } from \"../interfaces/IWBETH.sol\";\nimport { CorrelatedTokenOracle } from \"./common/CorrelatedTokenOracle.sol\";\n\n/**\n * @title WBETHOracle\n * @author Venus\n * @notice This oracle fetches the price of wBETH asset\n */\ncontract WBETHOracle is CorrelatedTokenOracle {\n /// @notice Constructor for the implementation contract.\n constructor(\n address wbeth,\n address eth,\n address resilientOracle,\n uint256 annualGrowthRate,\n uint256 _snapshotInterval,\n uint256 initialSnapshotMaxExchangeRate,\n uint256 initialSnapshotTimestamp,\n address accessControlManager,\n uint256 _snapshotGap\n )\n CorrelatedTokenOracle(\n wbeth,\n eth,\n resilientOracle,\n annualGrowthRate,\n _snapshotInterval,\n initialSnapshotMaxExchangeRate,\n initialSnapshotTimestamp,\n accessControlManager,\n _snapshotGap\n )\n {}\n\n /**\n * @notice Fetches the amount of ETH for 1 wBETH\n * @return amount The amount of ETH for wBETH\n */\n function getUnderlyingAmount() public view override returns (uint256) {\n return IWBETH(CORRELATED_TOKEN).exchangeRate();\n }\n}\n" + }, + "contracts/oracles/WeETHAccountantOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { CorrelatedTokenOracle } from \"./common/CorrelatedTokenOracle.sol\";\nimport { IAccountant } from \"../interfaces/IAccountant.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\n/**\n * @title WeETHAccountantOracle\n * @author Venus\n * @notice This oracle fetches the price of Ether.fi tokens based on an `Accountant` contract (i.e. weETHs and weETHk)\n */\ncontract WeETHAccountantOracle is CorrelatedTokenOracle {\n /// @notice Address of Accountant\n IAccountant public immutable ACCOUNTANT;\n\n /// @notice Constructor for the implementation contract.\n constructor(\n address accountant,\n address weethLRT,\n address weth,\n address resilientOracle,\n uint256 annualGrowthRate,\n uint256 _snapshotInterval,\n uint256 initialSnapshotMaxExchangeRate,\n uint256 initialSnapshotTimestamp,\n address accessControlManager,\n uint256 _snapshotGap\n )\n CorrelatedTokenOracle(\n weethLRT,\n weth,\n resilientOracle,\n annualGrowthRate,\n _snapshotInterval,\n initialSnapshotMaxExchangeRate,\n initialSnapshotTimestamp,\n accessControlManager,\n _snapshotGap\n )\n {\n ensureNonzeroAddress(accountant);\n ACCOUNTANT = IAccountant(accountant);\n }\n\n /**\n * @notice Gets the WETH for 1 weETH LRT\n * @return amount Amount of WETH\n */\n function getUnderlyingAmount() public view override returns (uint256) {\n return ACCOUNTANT.getRateSafe();\n }\n}\n" + }, + "contracts/oracles/WeETHOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { CorrelatedTokenOracle } from \"./common/CorrelatedTokenOracle.sol\";\nimport { IEtherFiLiquidityPool } from \"../interfaces/IEtherFiLiquidityPool.sol\";\nimport { EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\n/**\n * @title WeETHOracle\n * @author Venus\n * @notice This oracle fetches the price of weETH\n */\ncontract WeETHOracle is CorrelatedTokenOracle {\n /// @notice Address of Liqiudity pool\n IEtherFiLiquidityPool public immutable LIQUIDITY_POOL;\n\n /// @notice Constructor for the implementation contract.\n constructor(\n address liquidityPool,\n address weETH,\n address eETH,\n address resilientOracle,\n uint256 annualGrowthRate,\n uint256 _snapshotInterval,\n uint256 initialSnapshotMaxExchangeRate,\n uint256 initialSnapshotTimestamp,\n address accessControlManager,\n uint256 _snapshotGap\n )\n CorrelatedTokenOracle(\n weETH,\n eETH,\n resilientOracle,\n annualGrowthRate,\n _snapshotInterval,\n initialSnapshotMaxExchangeRate,\n initialSnapshotTimestamp,\n accessControlManager,\n _snapshotGap\n )\n {\n ensureNonzeroAddress(liquidityPool);\n LIQUIDITY_POOL = IEtherFiLiquidityPool(liquidityPool);\n }\n\n /**\n * @notice Gets the eETH for 1 weETH\n * @return amount Amount of eETH\n */\n function getUnderlyingAmount() public view override returns (uint256) {\n return LIQUIDITY_POOL.amountForShare(EXP_SCALE);\n }\n}\n" + }, + "contracts/oracles/WstETHOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { OracleInterface } from \"../interfaces/OracleInterface.sol\";\nimport { IStETH } from \"../interfaces/IStETH.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\n\n/**\n * @title WstETHOracle\n * @author Venus\n * @notice Depending on the equivalence flag price is either based on assumption that 1 stETH = 1 ETH\n * or the price of stETH/USD (secondary market price) is obtained from the oracle.\n */\ncontract WstETHOracle is OracleInterface {\n /// @notice A flag assuming 1:1 price equivalence between stETH/ETH\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n bool public immutable ASSUME_STETH_ETH_EQUIVALENCE;\n\n /// @notice Address of stETH\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n IStETH public immutable STETH;\n\n /// @notice Address of wstETH\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable WSTETH_ADDRESS;\n\n /// @notice Address of WETH\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable WETH_ADDRESS;\n\n /// @notice Address of Resilient Oracle\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n OracleInterface public immutable RESILIENT_ORACLE;\n\n /// @notice Constructor for the implementation contract.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address wstETHAddress,\n address wETHAddress,\n address stETHAddress,\n address resilientOracleAddress,\n bool assumeEquivalence\n ) {\n ensureNonzeroAddress(wstETHAddress);\n ensureNonzeroAddress(wETHAddress);\n ensureNonzeroAddress(stETHAddress);\n ensureNonzeroAddress(resilientOracleAddress);\n WSTETH_ADDRESS = wstETHAddress;\n WETH_ADDRESS = wETHAddress;\n STETH = IStETH(stETHAddress);\n RESILIENT_ORACLE = OracleInterface(resilientOracleAddress);\n ASSUME_STETH_ETH_EQUIVALENCE = assumeEquivalence;\n }\n\n /**\n * @notice Gets the USD price of wstETH asset\n * @dev Depending on the equivalence flag price is either based on assumption that 1 stETH = 1 ETH\n * or the price of stETH/USD (secondary market price) is obtained from the oracle\n * @param asset Address of wstETH\n * @return wstETH Price in USD scaled by 1e18\n */\n function getPrice(address asset) public view returns (uint256) {\n if (asset != WSTETH_ADDRESS) revert(\"wrong wstETH address\");\n\n // get stETH amount for 1 wstETH scaled by 1e18\n uint256 stETHAmount = STETH.getPooledEthByShares(1 ether);\n\n // price is scaled 1e18 (oracle returns 36 - asset decimal scale)\n uint256 stETHUSDPrice = RESILIENT_ORACLE.getPrice(ASSUME_STETH_ETH_EQUIVALENCE ? WETH_ADDRESS : address(STETH));\n\n // stETHAmount (for 1 wstETH) * stETHUSDPrice / 1e18\n return (stETHAmount * stETHUSDPrice) / EXP_SCALE;\n }\n}\n" + }, + "contracts/oracles/WstETHOracleV2.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IStETH } from \"../interfaces/IStETH.sol\";\nimport { CorrelatedTokenOracle } from \"./common/CorrelatedTokenOracle.sol\";\nimport { EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\n/**\n * @title WstETHOracleV2\n * @author Venus\n * @notice This oracle fetches the price of wstETH\n */\ncontract WstETHOracleV2 is CorrelatedTokenOracle {\n /// @notice Address of stETH\n IStETH public immutable STETH;\n\n /// @notice Constructor for the implementation contract.\n /// @dev The underlyingToken must be correlated so that 1 underlyingToken is equal to 1 stETH, because\n /// getUnderlyingAmount() implicitly assumes that\n constructor(\n address stETH,\n address wstETH,\n address underlyingToken,\n address resilientOracle,\n uint256 annualGrowthRate,\n uint256 _snapshotInterval,\n uint256 initialSnapshotMaxExchangeRate,\n uint256 initialSnapshotTimestamp,\n address accessControlManager,\n uint256 _snapshotGap\n )\n CorrelatedTokenOracle(\n wstETH,\n underlyingToken,\n resilientOracle,\n annualGrowthRate,\n _snapshotInterval,\n initialSnapshotMaxExchangeRate,\n initialSnapshotTimestamp,\n accessControlManager,\n _snapshotGap\n )\n {\n ensureNonzeroAddress(stETH);\n STETH = IStETH(stETH);\n }\n\n /**\n * @notice Gets the amount of underlyingToken for 1 wstETH, assuming that 1 underlyingToken is equivalent to 1 stETH\n * @return amount Amount of underlyingToken\n */\n function getUnderlyingAmount() public view override returns (uint256) {\n return STETH.getPooledEthByShares(EXP_SCALE);\n }\n}\n" + }, + "contracts/oracles/ZkETHOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IZkETH } from \"../interfaces/IZkETH.sol\";\nimport { CorrelatedTokenOracle } from \"./common/CorrelatedTokenOracle.sol\";\n\n/**\n * @title ZkETHOracle\n * @author Venus\n * @notice This oracle fetches the price of zkETH\n */\ncontract ZkETHOracle is CorrelatedTokenOracle {\n /// @notice Constructor for the implementation contract.\n constructor(\n address zkETH,\n address rzkETH,\n address resilientOracle,\n uint256 annualGrowthRate,\n uint256 _snapshotInterval,\n uint256 initialSnapshotMaxExchangeRate,\n uint256 initialSnapshotTimestamp,\n address accessControlManager,\n uint256 _snapshotGap\n )\n CorrelatedTokenOracle(\n zkETH,\n rzkETH,\n resilientOracle,\n annualGrowthRate,\n _snapshotInterval,\n initialSnapshotMaxExchangeRate,\n initialSnapshotTimestamp,\n accessControlManager,\n _snapshotGap\n )\n {}\n\n /**\n * @notice Gets the amount of rzkETH for 1 zkETH\n * @return amount Amount of rzkETH\n */\n function getUnderlyingAmount() public view override returns (uint256) {\n return IZkETH(CORRELATED_TOKEN).LSTPerToken();\n }\n}\n" + }, + "contracts/ReferenceOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2025 Venus\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { ResilientOracleInterface, OracleInterface } from \"./interfaces/OracleInterface.sol\";\n\n/**\n * @title ReferenceOracle\n * @author Venus\n * @notice Reference oracle is the oracle that is not used for production but required for\n * price monitoring. This oracle contains some extra configurations for assets required to\n * compute reference prices of their derivative assets (OneJump, ERC4626, Pendle, etc.)\n */\ncontract ReferenceOracle is Ownable2StepUpgradeable, OracleInterface {\n struct ExternalPrice {\n /// @notice asset address\n address asset;\n /// @notice price of the asset from an external source\n uint256 price;\n }\n\n /// @notice Slot to temporarily store price information from external sources\n /// like CMC/Coingecko, useful to compute prices of derivative assets based on\n /// prices of the base assets with no on chain price information\n bytes32 public constant PRICES_SLOT = keccak256(abi.encode(\"venus-protocol/oracle/ReferenceOracle/prices\"));\n\n /// @notice Resilient oracle address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ResilientOracleInterface public immutable RESILIENT_ORACLE;\n\n /// @notice Oracle configuration for assets\n mapping(address => OracleInterface) public oracles;\n\n /// @notice Event emitted when an oracle is set\n event OracleConfigured(address indexed asset, address indexed oracle);\n\n /**\n * @notice Constructor for the implementation contract. Sets immutable variables.\n * @param resilientOracle Resilient oracle address\n * @custom:error ZeroAddressNotAllowed is thrown if resilient oracle address is null\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(ResilientOracleInterface resilientOracle) {\n ensureNonzeroAddress(address(resilientOracle));\n RESILIENT_ORACLE = resilientOracle;\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract admin\n */\n function initialize() external initializer {\n __Ownable2Step_init();\n }\n\n /**\n * @notice Sets an oracle to use for a specific asset\n * @dev The production resilientOracle will be used if zero address is passed\n * @param asset Asset address\n * @param oracle Oracle address\n * @custom:access Only owner\n * @custom:error ZeroAddressNotAllowed is thrown if asset address is null\n * @custom:event Emits OracleConfigured event\n */\n function setOracle(address asset, OracleInterface oracle) external onlyOwner {\n ensureNonzeroAddress(asset);\n oracles[asset] = OracleInterface(oracle);\n emit OracleConfigured(asset, address(oracle));\n }\n\n /**\n * @notice Gets price of the asset assuming other assets have the defined price\n * @param asset asset address\n * @param externalPrices an array of prices for other assets\n * @return USD price in scaled decimal places\n */\n function getPriceAssuming(address asset, ExternalPrice[] memory externalPrices) external returns (uint256) {\n uint256 externalPricesCount = externalPrices.length;\n for (uint256 i = 0; i < externalPricesCount; ++i) {\n _storeExternalPrice(externalPrices[i].asset, externalPrices[i].price);\n }\n return _getPrice(asset);\n }\n\n /**\n * @notice Gets price of the asset\n * @param asset asset address\n * @return USD price in scaled decimal places\n */\n function getPrice(address asset) external view override returns (uint256) {\n return _getPrice(asset);\n }\n\n function _storeExternalPrice(address asset, uint256 price) internal {\n bytes32 slot = keccak256(abi.encode(PRICES_SLOT, asset));\n // solhint-disable-next-line no-inline-assembly\n assembly (\"memory-safe\") {\n tstore(slot, price)\n }\n }\n\n function _getPrice(address asset) internal view returns (uint256) {\n uint256 externalPrice = _loadExternalPrice(asset);\n if (externalPrice != 0) {\n return externalPrice;\n }\n OracleInterface oracle = oracles[asset];\n if (oracle != OracleInterface(address(0))) {\n return oracle.getPrice(asset);\n }\n return RESILIENT_ORACLE.getPrice(asset);\n }\n\n function _loadExternalPrice(address asset) internal view returns (uint256 value) {\n bytes32 slot = keccak256(abi.encode(PRICES_SLOT, asset));\n // solhint-disable-next-line no-inline-assembly\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n}\n" + }, + "contracts/ResilientOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity 0.8.25;\n\nimport { PausableUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport { VBep20Interface } from \"./interfaces/VBep20Interface.sol\";\nimport { OracleInterface, ResilientOracleInterface, BoundValidatorInterface } from \"./interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ICappedOracle } from \"./interfaces/ICappedOracle.sol\";\nimport { Transient } from \"./lib/Transient.sol\";\n\n/**\n * @title ResilientOracle\n * @author Venus\n * @notice The Resilient Oracle is the main contract that the protocol uses to fetch prices of assets.\n *\n * DeFi protocols are vulnerable to price oracle failures including oracle manipulation and incorrectly\n * reported prices. If only one oracle is used, this creates a single point of failure and opens a vector\n * for attacking the protocol.\n *\n * The Resilient Oracle uses multiple sources and fallback mechanisms to provide accurate prices and protect\n * the protocol from oracle attacks.\n *\n * For every market (vToken) we configure the main, pivot and fallback oracles. The oracles are configured per\n * vToken's underlying asset address. The main oracle oracle is the most trustworthy price source, the pivot\n * oracle is used as a loose sanity checker and the fallback oracle is used as a backup price source.\n *\n * To validate prices returned from two oracles, we use an upper and lower bound ratio that is set for every\n * market. The upper bound ratio represents the deviation between reported price (the price that’s being\n * validated) and the anchor price (the price we are validating against) above which the reported price will\n * be invalidated. The lower bound ratio presents the deviation between reported price and anchor price below\n * which the reported price will be invalidated. So for oracle price to be considered valid the below statement\n * should be true:\n\n```\nanchorRatio = anchorPrice/reporterPrice\nisValid = anchorRatio <= upperBoundAnchorRatio && anchorRatio >= lowerBoundAnchorRatio\n```\n\n * In most cases, Chainlink is used as the main oracle, other oracles are used as the pivot oracle depending\n * on which supports the given market and Binance oracle is used as the fallback oracle.\n *\n * For a fetched price to be valid it must be positive and not stagnant. If the price is invalid then we consider the\n * oracle to be stagnant and treat it like it's disabled.\n */\ncontract ResilientOracle is PausableUpgradeable, AccessControlledV8, ResilientOracleInterface {\n /**\n * @dev Oracle roles:\n * **main**: The most trustworthy price source\n * **pivot**: Price oracle used as a loose sanity checker\n * **fallback**: The backup source when main oracle price is invalidated\n */\n enum OracleRole {\n MAIN,\n PIVOT,\n FALLBACK\n }\n\n struct TokenConfig {\n /// @notice asset address\n address asset;\n /// @notice `oracles` stores the oracles based on their role in the following order:\n /// [main, pivot, fallback],\n /// It can be indexed with the corresponding enum OracleRole value\n address[3] oracles;\n /// @notice `enableFlagsForOracles` stores the enabled state\n /// for each oracle in the same order as `oracles`\n bool[3] enableFlagsForOracles;\n /// @notice `cachingEnabled` is a flag that indicates whether the asset price should be cached\n bool cachingEnabled;\n }\n\n uint256 public constant INVALID_PRICE = 0;\n\n /// @notice Native market address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable nativeMarket;\n\n /// @notice VAI address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable vai;\n\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\n /// and can serve as any underlying asset of a market that supports native tokens\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Slot to cache the asset's price, used for transient storage\n /// custom:storage-location erc7201:venus-protocol/oracle/ResilientOracle/cache\n /// keccak256(abi.encode(uint256(keccak256(\"venus-protocol/oracle/ResilientOracle/cache\")) - 1))\n /// & ~bytes32(uint256(0xff))\n bytes32 public constant CACHE_SLOT = 0x4e99ec55972332f5e0ef9c6623192c0401b609161bffae64d9ccdd7ad6cc7800;\n\n /// @notice Bound validator contract address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n BoundValidatorInterface public immutable boundValidator;\n\n mapping(address => TokenConfig) private tokenConfigs;\n\n event TokenConfigAdded(\n address indexed asset,\n address indexed mainOracle,\n address indexed pivotOracle,\n address fallbackOracle\n );\n\n /// Event emitted when an oracle is set\n event OracleSet(address indexed asset, address indexed oracle, uint256 indexed role);\n\n /// Event emitted when an oracle is enabled or disabled\n event OracleEnabled(address indexed asset, uint256 indexed role, bool indexed enable);\n\n /// Event emitted when an asset cachingEnabled flag is set\n event CachedEnabled(address indexed asset, bool indexed enabled);\n\n /**\n * @notice Checks whether an address is null or not\n */\n modifier notNullAddress(address someone) {\n if (someone == address(0)) revert(\"can't be zero address\");\n _;\n }\n\n /**\n * @notice Checks whether token config exists by checking whether asset is null address\n * @dev address can't be null, so it's suitable to be used to check the validity of the config\n * @param asset asset address\n */\n modifier checkTokenConfigExistence(address asset) {\n if (tokenConfigs[asset].asset == address(0)) revert(\"token config must exist\");\n _;\n }\n\n /// @notice Constructor for the implementation contract. Sets immutable variables.\n /// @dev nativeMarketAddress can be address(0) if on the chain we do not support native market\n /// (e.g vETH on ethereum would not be supported, only vWETH)\n /// @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\n /// @param vaiAddress The address of the VAI token (if there is VAI on the deployed chain).\n /// Set to address(0) of VAI is not existent.\n /// @param _boundValidator Address of the bound validator contract\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address nativeMarketAddress,\n address vaiAddress,\n BoundValidatorInterface _boundValidator\n ) notNullAddress(address(_boundValidator)) {\n nativeMarket = nativeMarketAddress;\n vai = vaiAddress;\n boundValidator = _boundValidator;\n\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract admin and sets the BoundValidator contract address\n * @param accessControlManager_ Address of the access control manager contract\n */\n function initialize(address accessControlManager_) external initializer {\n __AccessControlled_init(accessControlManager_);\n __Pausable_init();\n }\n\n /**\n * @notice Pauses oracle\n * @custom:access Only Governance\n */\n function pause() external {\n _checkAccessAllowed(\"pause()\");\n _pause();\n }\n\n /**\n * @notice Unpauses oracle\n * @custom:access Only Governance\n */\n function unpause() external {\n _checkAccessAllowed(\"unpause()\");\n _unpause();\n }\n\n /**\n * @notice Batch sets token configs\n * @param tokenConfigs_ Token config array\n * @custom:access Only Governance\n * @custom:error Throws a length error if the length of the token configs array is 0\n */\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\n if (tokenConfigs_.length == 0) revert(\"length can't be 0\");\n uint256 numTokenConfigs = tokenConfigs_.length;\n for (uint256 i; i < numTokenConfigs; ++i) {\n setTokenConfig(tokenConfigs_[i]);\n }\n }\n\n /**\n * @notice Sets oracle for a given asset and role.\n * @dev Supplied asset **must** exist and main oracle may not be null\n * @param asset Asset address\n * @param oracle Oracle address\n * @param role Oracle role\n * @custom:access Only Governance\n * @custom:error Null address error if main-role oracle address is null\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error TokenConfigExistance error is thrown if token config is not set\n * @custom:event Emits OracleSet event with asset address, oracle address and role of the oracle for the asset\n */\n function setOracle(\n address asset,\n address oracle,\n OracleRole role\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\n _checkAccessAllowed(\"setOracle(address,address,uint8)\");\n if (oracle == address(0) && role == OracleRole.MAIN) revert(\"can't set zero address to main oracle\");\n tokenConfigs[asset].oracles[uint256(role)] = oracle;\n emit OracleSet(asset, oracle, uint256(role));\n }\n\n /**\n * @notice Enables/ disables oracle for the input asset. Token config for the input asset **must** exist\n * @dev Configuration for the asset **must** already exist and the asset cannot be 0 address\n * @param asset Asset address\n * @param role Oracle role\n * @param enable Enabled boolean of the oracle\n * @custom:access Only Governance\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error TokenConfigExistance error is thrown if token config is not set\n * @custom:event Emits OracleEnabled event with asset address, role of the oracle and enabled flag\n */\n function enableOracle(\n address asset,\n OracleRole role,\n bool enable\n ) external notNullAddress(asset) checkTokenConfigExistence(asset) {\n _checkAccessAllowed(\"enableOracle(address,uint8,bool)\");\n tokenConfigs[asset].enableFlagsForOracles[uint256(role)] = enable;\n emit OracleEnabled(asset, uint256(role), enable);\n }\n\n /**\n * @notice Updates the capped main oracle snapshot.\n * @dev This function should always be called before calling getUnderlyingPrice\n * @param vToken vToken address\n */\n function updatePrice(address vToken) external override {\n address asset = _getUnderlyingAsset(vToken);\n _updateAssetPrice(asset);\n }\n\n /**\n * @notice Updates the capped main oracle snapshot.\n * @dev This function should always be called before calling getPrice\n * @param asset asset address\n */\n function updateAssetPrice(address asset) external {\n _updateAssetPrice(asset);\n }\n\n /**\n * @dev Gets token config by asset address\n * @param asset asset address\n * @return tokenConfig Config for the asset\n */\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {\n return tokenConfigs[asset];\n }\n\n /**\n * @notice Gets price of the underlying asset for a given vToken. Validation flow:\n * - Check if the oracle is paused globally\n * - Validate price from main oracle against pivot oracle\n * - Validate price from fallback oracle against pivot oracle if the first validation failed\n * - Validate price from main oracle against fallback oracle if the second validation failed\n * In the case that the pivot oracle is not available but main price is available and validation is successful,\n * main oracle price is returned.\n * @param vToken vToken address\n * @return price USD price in scaled decimal places.\n * @custom:error Paused error is thrown when resilent oracle is paused\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\n */\n function getUnderlyingPrice(address vToken) external view override returns (uint256) {\n if (paused()) revert(\"resilient oracle is paused\");\n\n address asset = _getUnderlyingAsset(vToken);\n return _getPrice(asset);\n }\n\n /**\n * @notice Gets price of the asset\n * @param asset asset address\n * @return price USD price in scaled decimal places.\n * @custom:error Paused error is thrown when resilent oracle is paused\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\n */\n function getPrice(address asset) external view override returns (uint256) {\n if (paused()) revert(\"resilient oracle is paused\");\n return _getPrice(asset);\n }\n\n /**\n * @notice Sets/resets single token configs.\n * @dev main oracle **must not** be a null address\n * @param tokenConfig Token config struct\n * @custom:access Only Governance\n * @custom:error NotNullAddress is thrown if asset address is null\n * @custom:error NotNullAddress is thrown if main-role oracle address for asset is null\n * @custom:event Emits TokenConfigAdded event when the asset config is set successfully by the authorized account\n * @custom:event Emits CachedEnabled event when the asset cachingEnabled flag is set successfully\n */\n function setTokenConfig(\n TokenConfig memory tokenConfig\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.oracles[uint256(OracleRole.MAIN)]) {\n _checkAccessAllowed(\"setTokenConfig(TokenConfig)\");\n\n tokenConfigs[tokenConfig.asset] = tokenConfig;\n emit TokenConfigAdded(\n tokenConfig.asset,\n tokenConfig.oracles[uint256(OracleRole.MAIN)],\n tokenConfig.oracles[uint256(OracleRole.PIVOT)],\n tokenConfig.oracles[uint256(OracleRole.FALLBACK)]\n );\n emit CachedEnabled(tokenConfig.asset, tokenConfig.cachingEnabled);\n }\n\n /**\n * @notice Gets oracle and enabled status by asset address\n * @param asset asset address\n * @param role Oracle role\n * @return oracle Oracle address based on role\n * @return enabled Enabled flag of the oracle based on token config\n */\n function getOracle(address asset, OracleRole role) public view returns (address oracle, bool enabled) {\n oracle = tokenConfigs[asset].oracles[uint256(role)];\n enabled = tokenConfigs[asset].enableFlagsForOracles[uint256(role)];\n }\n\n /**\n * @notice Updates the capped oracle snapshot.\n * @dev Cache the asset price and return if already cached\n * @param asset asset address\n */\n function _updateAssetPrice(address asset) internal {\n if (Transient.readCachedPrice(CACHE_SLOT, asset) != 0) {\n return;\n }\n\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\n if (mainOracle != address(0) && mainOracleEnabled) {\n // if main oracle is not CorrelatedTokenOracle it will revert so we need to catch the revert\n try ICappedOracle(mainOracle).updateSnapshot() {} catch {}\n }\n\n if (_isCacheEnabled(asset)) {\n uint256 price = _getPrice(asset);\n Transient.cachePrice(CACHE_SLOT, asset, price);\n }\n }\n\n /**\n * @notice Gets price for the provided asset\n * @param asset asset address\n * @return price USD price in scaled decimal places.\n * @custom:error Invalid resilient oracle price error is thrown if fetched prices from oracle is invalid\n */\n function _getPrice(address asset) internal view returns (uint256) {\n uint256 pivotPrice = INVALID_PRICE;\n uint256 price;\n\n price = Transient.readCachedPrice(CACHE_SLOT, asset);\n if (price != 0) {\n return price;\n }\n\n // Get pivot oracle price, Invalid price if not available or error\n (address pivotOracle, bool pivotOracleEnabled) = getOracle(asset, OracleRole.PIVOT);\n if (pivotOracleEnabled && pivotOracle != address(0)) {\n try OracleInterface(pivotOracle).getPrice(asset) returns (uint256 pricePivot) {\n pivotPrice = pricePivot;\n } catch {}\n }\n\n // Compare main price and pivot price, return main price and if validation was successful\n // note: In case pivot oracle is not available but main price is available and\n // validation is successful, the main oracle price is returned.\n (uint256 mainPrice, bool validatedPivotMain) = _getMainOraclePrice(\n asset,\n pivotPrice,\n pivotOracleEnabled && pivotOracle != address(0)\n );\n if (mainPrice != INVALID_PRICE && validatedPivotMain) return mainPrice;\n\n // Compare fallback and pivot if main oracle comparision fails with pivot\n // Return fallback price when fallback price is validated successfully with pivot oracle\n (uint256 fallbackPrice, bool validatedPivotFallback) = _getFallbackOraclePrice(asset, pivotPrice);\n if (fallbackPrice != INVALID_PRICE && validatedPivotFallback) return fallbackPrice;\n\n // Lastly compare main price and fallback price\n if (\n mainPrice != INVALID_PRICE &&\n fallbackPrice != INVALID_PRICE &&\n boundValidator.validatePriceWithAnchorPrice(asset, mainPrice, fallbackPrice)\n ) {\n return mainPrice;\n }\n\n revert(\"invalid resilient oracle price\");\n }\n\n /**\n * @notice Gets a price for the provided asset\n * @dev This function won't revert when price is 0, because the fallback oracle may still be\n * able to fetch a correct price\n * @param asset asset address\n * @param pivotPrice Pivot oracle price\n * @param pivotEnabled If pivot oracle is not empty and enabled\n * @return price USD price in scaled decimals\n * e.g. asset decimals is 8 then price is returned as 10**18 * 10**(18-8) = 10**28 decimals\n * @return pivotValidated Boolean representing if the validation of main oracle price\n * and pivot oracle price were successful\n * @custom:error Invalid price error is thrown if main oracle fails to fetch price of the asset\n * @custom:error Invalid price error is thrown if main oracle is not enabled or main oracle\n * address is null\n */\n function _getMainOraclePrice(\n address asset,\n uint256 pivotPrice,\n bool pivotEnabled\n ) internal view returns (uint256, bool) {\n (address mainOracle, bool mainOracleEnabled) = getOracle(asset, OracleRole.MAIN);\n if (mainOracleEnabled && mainOracle != address(0)) {\n try OracleInterface(mainOracle).getPrice(asset) returns (uint256 mainOraclePrice) {\n if (!pivotEnabled) {\n return (mainOraclePrice, true);\n }\n if (pivotPrice == INVALID_PRICE) {\n return (mainOraclePrice, false);\n }\n return (\n mainOraclePrice,\n boundValidator.validatePriceWithAnchorPrice(asset, mainOraclePrice, pivotPrice)\n );\n } catch {\n return (INVALID_PRICE, false);\n }\n }\n\n return (INVALID_PRICE, false);\n }\n\n /**\n * @dev This function won't revert when the price is 0 because getPrice checks if price is > 0\n * @param asset asset address\n * @return price USD price in 18 decimals\n * @return pivotValidated Boolean representing if the validation of fallback oracle price\n * and pivot oracle price were successfully\n * @custom:error Invalid price error is thrown if fallback oracle fails to fetch price of the asset\n * @custom:error Invalid price error is thrown if fallback oracle is not enabled or fallback oracle\n * address is null\n */\n function _getFallbackOraclePrice(address asset, uint256 pivotPrice) private view returns (uint256, bool) {\n (address fallbackOracle, bool fallbackEnabled) = getOracle(asset, OracleRole.FALLBACK);\n if (fallbackEnabled && fallbackOracle != address(0)) {\n try OracleInterface(fallbackOracle).getPrice(asset) returns (uint256 fallbackOraclePrice) {\n if (pivotPrice == INVALID_PRICE) {\n return (fallbackOraclePrice, false);\n }\n return (\n fallbackOraclePrice,\n boundValidator.validatePriceWithAnchorPrice(asset, fallbackOraclePrice, pivotPrice)\n );\n } catch {\n return (INVALID_PRICE, false);\n }\n }\n\n return (INVALID_PRICE, false);\n }\n\n /**\n * @dev This function returns the underlying asset of a vToken\n * @param vToken vToken address\n * @return asset underlying asset address\n */\n function _getUnderlyingAsset(address vToken) private view notNullAddress(vToken) returns (address asset) {\n if (vToken == nativeMarket) {\n asset = NATIVE_TOKEN_ADDR;\n } else if (vToken == vai) {\n asset = vai;\n } else {\n asset = VBep20Interface(vToken).underlying();\n }\n }\n\n /**\n * @dev This function checks if the asset price should be cached\n * @param asset asset address\n * @return bool true if caching is enabled, false otherwise\n */\n function _isCacheEnabled(address asset) private view returns (bool) {\n return tokenConfigs[asset].cachingEnabled;\n }\n}\n" + }, + "contracts/test/BEP20Harness.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract BEP20Harness is ERC20 {\n uint8 public decimalsInternal = 18;\n\n constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {\n decimalsInternal = decimals_;\n }\n\n function faucet(uint256 amount) external {\n _mint(msg.sender, amount);\n }\n\n function decimals() public view virtual override returns (uint8) {\n return decimalsInternal;\n }\n}\n" + }, + "contracts/test/MockAnkrBNB.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IAnkrBNB } from \"../interfaces/IAnkrBNB.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract MockAnkrBNB is ERC20, Ownable, IAnkrBNB {\n uint8 private immutable _decimals;\n uint256 public exchangeRate;\n\n constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) Ownable() {\n _decimals = decimals_;\n }\n\n function faucet(uint256 amount) external {\n _mint(msg.sender, amount);\n }\n\n function setSharesToBonds(uint256 rate) external onlyOwner {\n exchangeRate = rate;\n }\n\n function sharesToBonds(uint256 amount) external view override returns (uint256) {\n return (amount * exchangeRate) / (10 ** uint256(_decimals));\n }\n\n function decimals() public view virtual override(ERC20, IAnkrBNB) returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "contracts/test/MockAsBNB.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IAsBNB } from \"../interfaces/IAsBNB.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract MockAsBNB is ERC20, Ownable, IAsBNB {\n uint8 private immutable _decimals;\n address public minter;\n\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address minter_\n ) ERC20(name_, symbol_) Ownable() {\n _decimals = decimals_;\n minter = minter_;\n }\n\n function faucet(uint256 amount) external {\n _mint(msg.sender, amount);\n }\n\n function setMinter(address minter_) external onlyOwner {\n minter = minter_;\n }\n\n function decimals() public view virtual override(ERC20, IAsBNB) returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "contracts/test/MockAsBNBMinter.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport { IAsBNBMinter } from \"../interfaces/IAsBNBMinter.sol\";\n\ncontract MockAsBNBMinter is IAsBNBMinter {\n function convertToTokens(uint256 _amount) external pure override returns (uint256) {\n return _amount;\n }\n}\n" + }, + "contracts/test/MockCallPrice.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport { OracleInterface, ResilientOracleInterface } from \"../interfaces/OracleInterface.sol\";\n\ninterface CorrelatedTokenOracleInterface {\n function updateSnapshot() external;\n function getPrice(address asset) external view returns (uint256);\n}\n\ncontract MockCallPrice {\n function getMultiPrice(CorrelatedTokenOracleInterface oracle, address asset) public returns (uint256, uint256) {\n oracle.updateSnapshot();\n return (oracle.getPrice(asset), oracle.getPrice(asset));\n }\n\n function getUnderlyingPriceResilientOracle(\n ResilientOracleInterface oracle,\n address vToken\n ) public returns (uint256, uint256) {\n oracle.updatePrice(vToken);\n oracle.updatePrice(vToken);\n return (oracle.getUnderlyingPrice(vToken), oracle.getUnderlyingPrice(vToken));\n }\n\n function getAssetPriceResilientOracle(\n ResilientOracleInterface oracle,\n address asset\n ) public returns (uint256, uint256) {\n oracle.updateAssetPrice(asset);\n oracle.updateAssetPrice(asset);\n return (oracle.getPrice(asset), oracle.getPrice(asset));\n }\n}\n" + }, + "contracts/test/MockEtherFiLiquidityPool.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"../interfaces/IEtherFiLiquidityPool.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract MockEtherFiLiquidityPool is IEtherFiLiquidityPool, Ownable {\n /// @notice The amount of eETH per weETH scaled by 1e18\n uint256 public amountPerShare;\n\n constructor() Ownable() {}\n\n function setAmountPerShare(uint256 _amountPerShare) external onlyOwner {\n amountPerShare = _amountPerShare;\n }\n\n function amountForShare(uint256 _share) external view override returns (uint256) {\n return (_share * amountPerShare) / 1e18;\n }\n}\n" + }, + "contracts/test/MockSFrax.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { ISFrax } from \"../interfaces/ISFrax.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract MockSFrax is ERC20, Ownable, ISFrax {\n uint8 private immutable _decimals;\n uint256 public exchangeRate;\n\n constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) Ownable() {\n _decimals = decimals_;\n }\n\n function faucet(uint256 amount) external {\n _mint(msg.sender, amount);\n }\n\n function setRate(uint256 rate) external onlyOwner {\n exchangeRate = rate;\n }\n\n function convertToAssets(uint256 shares) external view override returns (uint256) {\n return (shares * exchangeRate) / (10 ** uint256(_decimals));\n }\n\n function decimals() public view virtual override(ERC20, ISFrax) returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "contracts/test/MockSimpleOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"../interfaces/OracleInterface.sol\";\n\ncontract MockSimpleOracle is OracleInterface {\n mapping(address => uint256) public prices;\n\n constructor() {\n //\n }\n\n function getUnderlyingPrice(address vToken) external view returns (uint256) {\n return prices[vToken];\n }\n\n function getPrice(address asset) external view returns (uint256) {\n return prices[asset];\n }\n\n function setPrice(address vToken, uint256 price) public {\n prices[vToken] = price;\n }\n}\n\ncontract MockBoundValidator is BoundValidatorInterface {\n mapping(address => bool) public validateResults;\n bool public twapUpdated;\n\n constructor() {\n //\n }\n\n function validatePriceWithAnchorPrice(\n address vToken,\n uint256 reporterPrice,\n uint256 anchorPrice\n ) external view returns (bool) {\n return validateResults[vToken];\n }\n\n function validateAssetPriceWithAnchorPrice(\n address asset,\n uint256 reporterPrice,\n uint256 anchorPrice\n ) external view returns (bool) {\n return validateResults[asset];\n }\n\n function setValidateResult(address token, bool pass) public {\n validateResults[token] = pass;\n }\n}\n" + }, + "contracts/test/MockV3Aggregator.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV2V3Interface.sol\";\n\n/**\n * @title MockV3Aggregator\n * @notice Based on the FluxAggregator contract\n * @notice Use this contract when you need to test\n * other contract's ability to read data from an\n * aggregator contract, but how the aggregator got\n * its answer is unimportant\n */\ncontract MockV3Aggregator is AggregatorV2V3Interface {\n uint256 public constant version = 0;\n\n uint8 public decimals;\n int256 public latestAnswer;\n uint256 public latestTimestamp;\n uint256 public latestRound;\n\n mapping(uint256 => int256) public getAnswer;\n mapping(uint256 => uint256) public getTimestamp;\n mapping(uint256 => uint256) private getStartedAt;\n\n constructor(uint8 _decimals, int256 _initialAnswer) {\n decimals = _decimals;\n updateAnswer(_initialAnswer);\n }\n\n function getRoundData(\n uint80 _roundId\n )\n external\n view\n returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)\n {\n return (_roundId, getAnswer[_roundId], getStartedAt[_roundId], getTimestamp[_roundId], _roundId);\n }\n\n function latestRoundData()\n external\n view\n returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)\n {\n return (\n uint80(latestRound),\n getAnswer[latestRound],\n getStartedAt[latestRound],\n getTimestamp[latestRound],\n uint80(latestRound)\n );\n }\n\n function description() external pure returns (string memory) {\n return \"v0.6/tests/MockV3Aggregator.sol\";\n }\n\n function updateAnswer(int256 _answer) public {\n latestAnswer = _answer;\n latestTimestamp = block.timestamp;\n latestRound++;\n getAnswer[latestRound] = _answer;\n getTimestamp[latestRound] = block.timestamp;\n getStartedAt[latestRound] = block.timestamp;\n }\n\n function updateRoundData(uint80 _roundId, int256 _answer, uint256 _timestamp, uint256 _startedAt) public {\n latestRound = _roundId;\n latestAnswer = _answer;\n latestTimestamp = _timestamp;\n getAnswer[latestRound] = _answer;\n getTimestamp[latestRound] = _timestamp;\n getStartedAt[latestRound] = _startedAt;\n }\n}\n" + }, + "contracts/test/MockWBETH.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IWBETH } from \"../interfaces/IWBETH.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract MockWBETH is ERC20, Ownable, IWBETH {\n uint8 private immutable _decimals;\n uint256 public override exchangeRate;\n\n constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) Ownable() {\n _decimals = decimals_;\n }\n\n function faucet(uint256 amount) external {\n _mint(msg.sender, amount);\n }\n\n function setExchangeRate(uint256 rate) external onlyOwner {\n exchangeRate = rate;\n }\n\n function decimals() public view virtual override(ERC20, IWBETH) returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "contracts/test/oracles/MockCorrelatedTokenOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { CorrelatedTokenOracle } from \"../../oracles/common/CorrelatedTokenOracle.sol\";\n\ncontract MockCorrelatedTokenOracle is CorrelatedTokenOracle {\n uint256 public mockUnderlyingAmount;\n\n constructor(\n address correlatedToken,\n address underlyingToken,\n address resilientOracle,\n uint256 annualGrowthRate,\n uint256 snapshotInterval,\n uint256 initialSnapshotMaxExchangeRate,\n uint256 initialSnapshotTimestamp,\n address accessControlManager,\n uint256 snapshotGap\n )\n CorrelatedTokenOracle(\n correlatedToken,\n underlyingToken,\n resilientOracle,\n annualGrowthRate,\n snapshotInterval,\n initialSnapshotMaxExchangeRate,\n initialSnapshotTimestamp,\n accessControlManager,\n snapshotGap\n )\n {}\n\n function setMockUnderlyingAmount(uint256 amount) external {\n mockUnderlyingAmount = amount;\n }\n\n function getUnderlyingAmount() public view override returns (uint256) {\n return mockUnderlyingAmount;\n }\n}\n" + }, + "contracts/test/oracles/MockERC20.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract MockERC20 is ERC20 {\n constructor(string memory name, string memory symbol, uint8 decimals) ERC20(name, symbol) {\n _mint(msg.sender, 100000 * 10 ** uint256(decimals));\n }\n}\n" + }, + "contracts/test/oracles/MockResilientOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"../../interfaces/OracleInterface.sol\";\n\ncontract MockOracle is OracleInterface {\n mapping(address => uint256) public prices;\n\n function getPrice(address asset) external view returns (uint256) {\n return prices[asset];\n }\n\n function setPrice(address vToken, uint256 price) public {\n prices[vToken] = price;\n }\n}\n" + }, + "contracts/test/PancakePairHarness.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n// a library for performing various math operations\n\nlibrary Math {\n function min(uint256 x, uint256 y) internal pure returns (uint256 z) {\n z = x < y ? x : y;\n }\n\n // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)\n function sqrt(uint256 y) internal pure returns (uint256 z) {\n if (y > 3) {\n z = y;\n uint256 x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n}\n\n// range: [0, 2**112 - 1]\n// resolution: 1 / 2**112\n\nlibrary UQ112x112 {\n //solhint-disable-next-line state-visibility\n uint224 constant Q112 = 2 ** 112;\n\n // encode a uint112 as a UQ112x112\n function encode(uint112 y) internal pure returns (uint224 z) {\n z = uint224(y) * Q112; // never overflows\n }\n\n // divide a UQ112x112 by a uint112, returning a UQ112x112\n function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {\n z = x / uint224(y);\n }\n}\n\ncontract PancakePairHarness {\n using UQ112x112 for uint224;\n\n address public token0;\n address public token1;\n\n uint112 private reserve0; // uses single storage slot, accessible via getReserves\n uint112 private reserve1; // uses single storage slot, accessible via getReserves\n uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves\n\n uint256 public price0CumulativeLast;\n uint256 public price1CumulativeLast;\n uint256 public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event\n\n // called once by the factory at time of deployment\n function initialize(address _token0, address _token1) external {\n token0 = _token0;\n token1 = _token1;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function update(uint256 balance0, uint256 balance1, uint112 _reserve0, uint112 _reserve1) external {\n require(balance0 <= type(uint112).max && balance1 <= type(uint112).max, \"PancakeV2: OVERFLOW\");\n uint32 blockTimestamp = uint32(block.timestamp % 2 ** 32);\n unchecked {\n uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n // * never overflows, and + overflow is desired\n price0CumulativeLast += uint256(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;\n price1CumulativeLast += uint256(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;\n }\n }\n reserve0 = uint112(balance0);\n reserve1 = uint112(balance1);\n blockTimestampLast = blockTimestamp;\n }\n\n function currentBlockTimestamp() external view returns (uint32) {\n return uint32(block.timestamp % 2 ** 32);\n }\n\n function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n}\n" + }, + "contracts/test/VBEP20Harness.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"./BEP20Harness.sol\";\n\ncontract VBEP20Harness is BEP20Harness {\n /**\n * @notice Underlying asset for this VToken\n */\n address public underlying;\n\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimals,\n address underlying_\n ) BEP20Harness(name_, symbol_, decimals) {\n underlying = underlying_;\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor (address initialOwner) {\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Proxy.sol\";\nimport \"./ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n *\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\n */\n constructor(address _logic, bytes memory _data) payable {\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1));\n _upgradeToAndCall(_logic, _data, false);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function _implementation() internal view virtual override returns (address impl) {\n return ERC1967Upgrade._getImplementation();\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view virtual returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Emitted when the beacon is upgraded.\n */\n event BeaconUpgraded(address indexed beacon);\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(Address.isContract(IBeacon(newBeacon).implementation()), \"ERC1967: beacon implementation is not a contract\");\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(\n address newBeacon,\n bytes memory data,\n bool forceCall\n ) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internall call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overriden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./TransparentUpgradeableProxy.sol\";\nimport \"../../access/Ownable.sol\";\n\n/**\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\n */\ncontract ProxyAdmin is Ownable {\n\n constructor (address initialOwner) Ownable(initialOwner) {}\n\n /**\n * @dev Returns the current implementation of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"implementation()\")) == 0x5c60da1b\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"5c60da1b\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Returns the current admin of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"admin()\")) == 0xf851a440\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"f851a440\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Changes the admin of `proxy` to `newAdmin`.\n *\n * Requirements:\n *\n * - This contract must be the current admin of `proxy`.\n */\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\n proxy.changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\n proxy.upgradeTo(implementation);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgradeAndCall(\n TransparentUpgradeableProxy proxy,\n address implementation,\n bytes memory data\n ) public payable virtual onlyOwner {\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n */\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n */\n constructor(\n address _logic,\n address admin_,\n bytes memory _data\n ) payable ERC1967Proxy(_logic, _data) {\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n _changeAdmin(admin_);\n }\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n */\n modifier ifAdmin() {\n if (msg.sender == _getAdmin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function admin() external ifAdmin returns (address admin_) {\n admin_ = _getAdmin();\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function implementation() external ifAdmin returns (address implementation_) {\n implementation_ = _implementation();\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\n */\n function changeAdmin(address newAdmin) external virtual ifAdmin {\n _changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n */\n function upgradeTo(address newImplementation) external ifAdmin {\n _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n _upgradeToAndCall(newImplementation, data, true);\n }\n\n /**\n * @dev Returns the current admin.\n */\n function _admin() internal view virtual returns (address) {\n return _getAdmin();\n }\n\n /**\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n */\n function _beforeFallback() internal virtual override {\n require(msg.sender != _getAdmin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n super._beforeFallback();\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n assembly {\n r.slot := slot\n }\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/proxy/OptimizedTransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n */\ncontract OptimizedTransparentUpgradeableProxy is ERC1967Proxy {\n address internal immutable _ADMIN;\n\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n */\n constructor(\n address _logic,\n address admin_,\n bytes memory _data\n ) payable ERC1967Proxy(_logic, _data) {\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n _ADMIN = admin_;\n\n // still store it to work with EIP-1967\n bytes32 slot = _ADMIN_SLOT;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sstore(slot, admin_)\n }\n emit AdminChanged(address(0), admin_);\n }\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n */\n modifier ifAdmin() {\n if (msg.sender == _getAdmin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function admin() external ifAdmin returns (address admin_) {\n admin_ = _getAdmin();\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function implementation() external ifAdmin returns (address implementation_) {\n implementation_ = _implementation();\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n */\n function upgradeTo(address newImplementation) external ifAdmin {\n _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n _upgradeToAndCall(newImplementation, data, true);\n }\n\n /**\n * @dev Returns the current admin.\n */\n function _admin() internal view virtual returns (address) {\n return _getAdmin();\n }\n\n /**\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n */\n function _beforeFallback() internal virtual override {\n require(msg.sender != _getAdmin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n super._beforeFallback();\n }\n\n function _getAdmin() internal view virtual override returns (address) {\n return _ADMIN;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200, + "details": { + "yul": true + } + }, + "evmVersion": "cancun", + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/bsctestnet_addresses.json b/deployments/bsctestnet_addresses.json index 4c3b63e7..d6de5c58 100644 --- a/deployments/bsctestnet_addresses.json +++ b/deployments/bsctestnet_addresses.json @@ -27,6 +27,7 @@ "PendleOracle-PT-clisBNB-24APR2025": "0xeF663663e802Ff4510aDE14975820FFB5d2EE9E8", "PendleOracle-PT-clisBNB-24APR2025_Implementation": "0x6d8b4d49238ffc3Ad23239fbC3045307B98D6F76", "PendleOracle-PT-clisBNB-24APR2025_Proxy": "0xeF663663e802Ff4510aDE14975820FFB5d2EE9E8", + "PendleOracle-PT-clisBNB-25JUN2026": "0x86EB1cE03e825CFD4516F385d7b90DE72B90BF69", "PendleOracle-PT-sUSDe-26JUN2025": "0x85201328baa52061E6648d9b4c285529411Cd33B", "PythOracle": "0x94E1534c14e0736BB24decA625f2F5364B198E0C", "PythOracle_Implementation": "0xb8a450101DF8ab770c8F8521E189a4B39e7Cf5f5", diff --git a/helpers/deploymentConfig.ts b/helpers/deploymentConfig.ts index 1356e6a2..ee0a1a9e 100644 --- a/helpers/deploymentConfig.ts +++ b/helpers/deploymentConfig.ts @@ -104,6 +104,7 @@ export const ADDRESSES: PreconfiguredAddresses = { USDe: "0x986C30591f5aAb401ea3aa63aFA595608721B1B9", xSolvBTC: "0x3ea87323806586A0282b50377e0FEa76070F532B", SolvBTC: "0x6855E14A6df91b8E4D55163d068E9ef2530fd4CE", + "PT-clisBNB-25JUN2026": "0x60825e8eBbed5C32c1DAA7eA68ceCA70BEA65040", }, bscmainnet: { vBNBAddress: mainnetDeployments.contracts.vBNB.address, @@ -141,6 +142,8 @@ export const ADDRESSES: PreconfiguredAddresses = { USDe: "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34", xSolvBTC: "0x1346b618dC92810EC74163e4c27004c921D446a5", SolvBTC: "0x4aae823a6a0b376De6A78e74eCC5b079d38cBCf7", + "PT-clisBNB-25JUN2026": "0xe052823b4aefc6e230FAf46231A57d0905E30AE0", + "PT-clisBNB-25JUN2026_Market": "0x3C1a3D6B69A866444Fe506F7D38a00a1C2D859C5", }, sepolia: { vBNBAddress: ethers.constants.AddressZero,