From b21aacab3ee099cba0ed1152acfad47257c2b75e Mon Sep 17 00:00:00 2001 From: Pablo Veyrat Date: Wed, 24 Jan 2024 15:24:57 +0100 Subject: [PATCH 1/7] feat: silo oracle --- .../EUR/OracleSTEURETHChainlinkArbitrum.sol | 35 ++++++++++++++++++ deploy/newOracle/newOracle.ts | 37 +++++++++++++++++++ e2e/arbitrum/oraclesChainlink.test.ts | 16 ++++++++ hardhat.config.ts | 8 ++-- package.json | 1 + 5 files changed, 92 insertions(+), 5 deletions(-) create mode 100644 contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol create mode 100644 deploy/newOracle/newOracle.ts diff --git a/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol b/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol new file mode 100644 index 00000000..9f2ad2ae --- /dev/null +++ b/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.12; + +import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; + +import "../../../BaseOracleChainlinkMultiTwoFeeds.sol"; +import "../../../../interfaces/external/IERC4626.sol"; + +/// @title OracleSTEURETHChainlinkArbitrum +/// @author Angle Labs, Inc. +/// @notice Gives the price of stEUR in ETH in base 18 +contract OracleSTEURETHChainlinkArbitrum is BaseOracleChainlinkMultiTwoFeeds { + string public constant DESCRIPTION = "stEUR/ETH Oracle"; + IERC4626 public constant STEUR = IERC4626(0x004626A008B1aCdC4c74ab51644093b155e59A23); + + constructor(uint32 _stalePeriod, address _treasury) BaseOracleChainlinkMultiTwoFeeds(_stalePeriod, _treasury) {} + + /// @inheritdoc IOracle + function circuitChainlink() public pure override returns (AggregatorV3Interface[] memory) { + AggregatorV3Interface[] memory _circuitChainlink = new AggregatorV3Interface[](2); + // Oracle agEUR/USD + _circuitChainlink[0] = AggregatorV3Interface(0x37963F10245e7c3a10c0E9d43a6E617B4Bc8440A); + // Oracle ETH/USD + _circuitChainlink[1] = AggregatorV3Interface(0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612); + return _circuitChainlink; + } + + /// @inheritdoc BaseOracleChainlinkMultiTwoFeeds + function _getQuoteAmount() internal view override returns (uint256) { + return STEUR.convertToAssets(1 ether); + } + + // TODO: latestAnswer +} diff --git a/deploy/newOracle/newOracle.ts b/deploy/newOracle/newOracle.ts new file mode 100644 index 00000000..8afeb829 --- /dev/null +++ b/deploy/newOracle/newOracle.ts @@ -0,0 +1,37 @@ +import { DeployFunction } from 'hardhat-deploy/types'; +import yargs from 'yargs'; + +import { OracleSTEURETHChainlinkArbitrum, OracleSTEURETHChainlinkArbitrum__factory } from '../../typechain'; + +const argv = yargs.env('').boolean('ci').parseSync(); + +const func: DeployFunction = async ({ deployments, ethers, network }) => { + const { deploy } = deployments; + const { deployer } = await ethers.getNamedSigners(); + + // const treasury = (await deployments.get(`Treasury`)).address; + const treasury = '0x37963F10245e7c3a10c0E9d43a6E617B4Bc8440A'; + console.log('Now deploying the Oracle wstETH/USD'); + console.log(`Treasury: ${treasury}`); + await deploy('Oracle_STEUR_ETH', { + contract: `OracleSTEURETHChainlinkArbitrum`, + from: deployer.address, + args: [3600 * 36, treasury], + log: !argv.ci, + }); + const oracle = (await deployments.get('Oracle_STEUR_ETH')).address; + console.log(`Successfully deployed Oracle stEUR/ETH at the address ${oracle}`); + + const oracleContract = new ethers.Contract( + oracle, + OracleSTEURETHChainlinkArbitrum__factory.createInterface(), + deployer, + ) as OracleSTEURETHChainlinkArbitrum; + + const oracleValue = await oracleContract.read(); + console.log('Oracle value', oracleValue.toString()); + console.log(''); +}; + +func.tags = ['newOracle']; +export default func; diff --git a/e2e/arbitrum/oraclesChainlink.test.ts b/e2e/arbitrum/oraclesChainlink.test.ts index e90a7b9e..b69efa75 100644 --- a/e2e/arbitrum/oraclesChainlink.test.ts +++ b/e2e/arbitrum/oraclesChainlink.test.ts @@ -10,6 +10,8 @@ import { MockTreasury__factory, OracleBTCEURChainlinkArbitrum, OracleBTCEURChainlinkArbitrum__factory, + OracleSTEURETHChainlinkArbitrum, + OracleSTEURETHChainlinkArbitrum__factory, } from '../../typechain'; contract('Oracles Chainlink', () => { @@ -18,6 +20,7 @@ contract('Oracles Chainlink', () => { let bob: SignerWithAddress; let oracleBTC: OracleBTCEURChainlinkArbitrum; + let oracleSTEUR: OracleSTEURETHChainlinkArbitrum; let stalePeriod: BigNumber; let treasury: MockTreasury; @@ -33,6 +36,7 @@ contract('Oracles Chainlink', () => { ZERO_ADDRESS, )) as MockTreasury; oracleBTC = await new OracleBTCEURChainlinkArbitrum__factory(deployer).deploy(stalePeriod, treasury.address); + oracleSTEUR = await new OracleSTEURETHChainlinkArbitrum__factory(deployer).deploy(stalePeriod, treasury.address); }); describe('Oracle BTC', () => { @@ -47,4 +51,16 @@ contract('Oracles Chainlink', () => { expect(await oracleBTC.treasury()).to.be.equal(treasury.address); }); }); + describe('Oracle stEUR', () => { + it('read', async () => { + const receipt = await oracleSTEUR.read(); + const gas = await oracleSTEUR.estimateGas.read(); + console.log(gas.toString()); + console.log(receipt.toString()); + }); + it('initialization', async () => { + expect(await oracleSTEUR.stalePeriod()).to.be.equal(stalePeriod); + expect(await oracleSTEUR.treasury()).to.be.equal(treasury.address); + }); + }); }); diff --git a/hardhat.config.ts b/hardhat.config.ts index 72c4d5dc..63cdbb0b 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -146,10 +146,10 @@ const config: HardhatUserConfig = { forking: { enabled: argv.fork || false, // Mainnet - + /* url: nodeUrl('mainnet'), blockNumber: 18976806, - + */ // Polygon /* url: nodeUrl('forkpolygon'), @@ -162,10 +162,8 @@ const config: HardhatUserConfig = { blockNumber: 114397708, */ // Arbitrum - /* url: nodeUrl('arbitrum'), - blockNumber: 19356874, - */ + blockNumber: 173676662, // Avalanche /* url: nodeUrl('avalanche'), diff --git a/package.json b/package.json index 349c0426..beef0d96 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "size": "yarn hardhat:compile && hardhat size-contracts", "hardhat:test": "hardhat test", "test:e2e:mainnet": "FORK=true hardhat test e2e/mainnet/oraclesChainlink.test.ts", + "test:e2e:arbitrum": "FORK=true hardhat test e2e/arbitrum/oraclesChainlink.test.ts", "test:e2e:balance": "FORK=true hardhat test e2e/mainnet/balanceOf.test.ts", "test:e2e": "FORK=true hardhat test", "test:all": "yarn test && yarn test:e2e:mainnet", From c7db1f4cf4a93222e0348d1d0e9eb524364dbcd0 Mon Sep 17 00:00:00 2001 From: Pablo Veyrat Date: Wed, 24 Jan 2024 15:47:38 +0100 Subject: [PATCH 2/7] feat: oracle --- .../oracle/BaseOracleChainlinkMultiTwoFeeds.sol | 2 +- .../EUR/OracleSTEURETHChainlinkArbitrum.sol | 15 ++++++++++++++- .../mainnet/EUR/OracleCBETHEURChainlink.sol | 2 +- .../mainnet/EUR/OracleHIGHEURChainlink.sol | 2 +- e2e/arbitrum/oraclesChainlink.test.ts | 10 ++++++++++ 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/contracts/oracle/BaseOracleChainlinkMultiTwoFeeds.sol b/contracts/oracle/BaseOracleChainlinkMultiTwoFeeds.sol index a28d2919..4b977138 100644 --- a/contracts/oracle/BaseOracleChainlinkMultiTwoFeeds.sol +++ b/contracts/oracle/BaseOracleChainlinkMultiTwoFeeds.sol @@ -19,7 +19,7 @@ abstract contract BaseOracleChainlinkMultiTwoFeeds is BaseOracleChainlinkMulti { } /// @inheritdoc IOracle - function read() external view virtual override returns (uint256 quoteAmount) { + function read() public view virtual override returns (uint256 quoteAmount) { quoteAmount = _getQuoteAmount(); AggregatorV3Interface[] memory _circuitChainlink = circuitChainlink(); uint8[2] memory circuitChainIsMultiplied = [1, 0]; diff --git a/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol b/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol index 9f2ad2ae..215a00c0 100644 --- a/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol +++ b/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol @@ -31,5 +31,18 @@ contract OracleSTEURETHChainlinkArbitrum is BaseOracleChainlinkMultiTwoFeeds { return STEUR.convertToAssets(1 ether); } - // TODO: latestAnswer + /// @notice Returns the decimals of the oracle + function decimals() external pure returns (uint8) { + return 18; + } + + /// @notice Chainlink interface compatibility + /// @return roundID + /// @return aggregatorPrice + /// @return startedAt + /// @return timestamp + /// @return answeredInRound + function latestRoundData() external view returns (uint80, int256, uint256, uint256, uint80) { + return (0, int256(read()), 0, block.timestamp, 0); + } } diff --git a/contracts/oracle/implementations/mainnet/EUR/OracleCBETHEURChainlink.sol b/contracts/oracle/implementations/mainnet/EUR/OracleCBETHEURChainlink.sol index 54358075..f9fbd6c6 100644 --- a/contracts/oracle/implementations/mainnet/EUR/OracleCBETHEURChainlink.sol +++ b/contracts/oracle/implementations/mainnet/EUR/OracleCBETHEURChainlink.sol @@ -27,7 +27,7 @@ contract OracleCBETHEURChainlink is BaseOracleChainlinkMultiTwoFeeds { } /// @inheritdoc BaseOracleChainlinkMultiTwoFeeds - function read() external view virtual override returns (uint256 quoteAmount) { + function read() public view virtual override returns (uint256 quoteAmount) { quoteAmount = _getQuoteAmount(); AggregatorV3Interface[] memory _circuitChainlink = circuitChainlink(); uint8[3] memory circuitChainIsMultiplied = [1, 1, 0]; diff --git a/contracts/oracle/implementations/mainnet/EUR/OracleHIGHEURChainlink.sol b/contracts/oracle/implementations/mainnet/EUR/OracleHIGHEURChainlink.sol index a4774582..8bda6e39 100644 --- a/contracts/oracle/implementations/mainnet/EUR/OracleHIGHEURChainlink.sol +++ b/contracts/oracle/implementations/mainnet/EUR/OracleHIGHEURChainlink.sol @@ -23,7 +23,7 @@ contract OracleHIGHEURChainlink is BaseOracleChainlinkMultiTwoFeeds { } /// @inheritdoc BaseOracleChainlinkMultiTwoFeeds - function read() external view override returns (uint256 quoteAmount) { + function read() public view override returns (uint256 quoteAmount) { quoteAmount = _readChainlinkFeed(_getQuoteAmount(), circuitChainlink()[0], 1, 8); } } diff --git a/e2e/arbitrum/oraclesChainlink.test.ts b/e2e/arbitrum/oraclesChainlink.test.ts index b69efa75..c6897adf 100644 --- a/e2e/arbitrum/oraclesChainlink.test.ts +++ b/e2e/arbitrum/oraclesChainlink.test.ts @@ -57,6 +57,16 @@ contract('Oracles Chainlink', () => { const gas = await oracleSTEUR.estimateGas.read(); console.log(gas.toString()); console.log(receipt.toString()); + + const latestAnswer = await oracleSTEUR.latestRoundData(); + console.log( + latestAnswer[0].toString(), + latestAnswer[1].toString(), + latestAnswer[2].toString(), + latestAnswer[3].toString(), + latestAnswer[4].toString(), + ); + expect(await oracleSTEUR.decimals()).to.be.equal(18); }); it('initialization', async () => { expect(await oracleSTEUR.stalePeriod()).to.be.equal(stalePeriod); From c52b8768a21cbe9eaa73e65eaa28c61fbd6e7511 Mon Sep 17 00:00:00 2001 From: Pablo Veyrat Date: Thu, 25 Jan 2024 09:09:25 +0100 Subject: [PATCH 3/7] update oracle name --- deploy/newOracle/newOracle.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deploy/newOracle/newOracle.ts b/deploy/newOracle/newOracle.ts index 8afeb829..0a99a912 100644 --- a/deploy/newOracle/newOracle.ts +++ b/deploy/newOracle/newOracle.ts @@ -10,8 +10,9 @@ const func: DeployFunction = async ({ deployments, ethers, network }) => { const { deployer } = await ethers.getNamedSigners(); // const treasury = (await deployments.get(`Treasury`)).address; + // Treasury_EUR Arbitrum const treasury = '0x37963F10245e7c3a10c0E9d43a6E617B4Bc8440A'; - console.log('Now deploying the Oracle wstETH/USD'); + console.log('Now deploying the Oracle stEUR/ETH'); console.log(`Treasury: ${treasury}`); await deploy('Oracle_STEUR_ETH', { contract: `OracleSTEURETHChainlinkArbitrum`, From 75c13e6aeb8c7c974de4b86dfbeb80de805a2c50 Mon Sep 17 00:00:00 2001 From: Pablo Veyrat Date: Thu, 25 Jan 2024 11:17:12 +0100 Subject: [PATCH 4/7] adjust treasury address --- deploy/newOracle/newOracle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/newOracle/newOracle.ts b/deploy/newOracle/newOracle.ts index 0a99a912..146b67e7 100644 --- a/deploy/newOracle/newOracle.ts +++ b/deploy/newOracle/newOracle.ts @@ -11,7 +11,7 @@ const func: DeployFunction = async ({ deployments, ethers, network }) => { // const treasury = (await deployments.get(`Treasury`)).address; // Treasury_EUR Arbitrum - const treasury = '0x37963F10245e7c3a10c0E9d43a6E617B4Bc8440A'; + const treasury = '0x0D710512E100C171139D2Cf5708f22C680eccF52'; console.log('Now deploying the Oracle stEUR/ETH'); console.log(`Treasury: ${treasury}`); await deploy('Oracle_STEUR_ETH', { From 64a1d47c5eb68ab35fb61109a60131a202ed2f4d Mon Sep 17 00:00:00 2001 From: Pablo Veyrat Date: Thu, 25 Jan 2024 11:41:01 +0100 Subject: [PATCH 5/7] feat: chainlink interface --- .../EUR/OracleSTEURETHChainlinkArbitrum.sol | 28 +++++++++++++++---- e2e/arbitrum/oraclesChainlink.test.ts | 8 ++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol b/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol index 215a00c0..64de0527 100644 --- a/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol +++ b/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol @@ -10,7 +10,7 @@ import "../../../../interfaces/external/IERC4626.sol"; /// @title OracleSTEURETHChainlinkArbitrum /// @author Angle Labs, Inc. /// @notice Gives the price of stEUR in ETH in base 18 -contract OracleSTEURETHChainlinkArbitrum is BaseOracleChainlinkMultiTwoFeeds { +contract OracleSTEURETHChainlinkArbitrum is BaseOracleChainlinkMultiTwoFeeds, AggregatorV3Interface { string public constant DESCRIPTION = "stEUR/ETH Oracle"; IERC4626 public constant STEUR = IERC4626(0x004626A008B1aCdC4c74ab51644093b155e59A23); @@ -19,9 +19,9 @@ contract OracleSTEURETHChainlinkArbitrum is BaseOracleChainlinkMultiTwoFeeds { /// @inheritdoc IOracle function circuitChainlink() public pure override returns (AggregatorV3Interface[] memory) { AggregatorV3Interface[] memory _circuitChainlink = new AggregatorV3Interface[](2); - // Oracle agEUR/USD + // Oracle agEUR/USD - Redstone _circuitChainlink[0] = AggregatorV3Interface(0x37963F10245e7c3a10c0E9d43a6E617B4Bc8440A); - // Oracle ETH/USD + // Oracle ETH/USD - Chainlink _circuitChainlink[1] = AggregatorV3Interface(0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612); return _circuitChainlink; } @@ -31,18 +31,34 @@ contract OracleSTEURETHChainlinkArbitrum is BaseOracleChainlinkMultiTwoFeeds { return STEUR.convertToAssets(1 ether); } - /// @notice Returns the decimals of the oracle + /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + CHAINLINK INTERFACE COMPATIBILITY + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ + function decimals() external pure returns (uint8) { return 18; } - /// @notice Chainlink interface compatibility + function description() external pure returns (string memory desc) { + desc = "Angle stEUR/ETH Price Feed"; + } + + function version() external pure returns (uint256) { + return 1; + } + /// @return roundID /// @return aggregatorPrice /// @return startedAt /// @return timestamp /// @return answeredInRound - function latestRoundData() external view returns (uint80, int256, uint256, uint256, uint80) { + /// @dev The roundId, startedAt and answeredInRound values return in this function must be disregarded + function latestRoundData() public view returns (uint80, int256, uint256, uint256, uint80) { return (0, int256(read()), 0, block.timestamp, 0); } + + /// @dev This function always returns the latestRoundData + function getRoundData(uint80) external view returns (uint80, int256, uint256, uint256, uint80) { + return latestRoundData(); + } } diff --git a/e2e/arbitrum/oraclesChainlink.test.ts b/e2e/arbitrum/oraclesChainlink.test.ts index c6897adf..70ac7ef0 100644 --- a/e2e/arbitrum/oraclesChainlink.test.ts +++ b/e2e/arbitrum/oraclesChainlink.test.ts @@ -67,6 +67,14 @@ contract('Oracles Chainlink', () => { latestAnswer[4].toString(), ); expect(await oracleSTEUR.decimals()).to.be.equal(18); + expect(await oracleSTEUR.description()).to.be.equal('Angle stEUR/ETH Price Feed'); + expect(await oracleSTEUR.version()).to.be.equal(1); + const answer = await oracleSTEUR.getRoundData(1); + expect(answer[0]).to.be.equal(latestAnswer[0]); + expect(answer[1]).to.be.equal(latestAnswer[1]); + expect(answer[2]).to.be.equal(latestAnswer[2]); + expect(answer[3]).to.be.equal(latestAnswer[3]); + expect(answer[4]).to.be.equal(latestAnswer[4]); }); it('initialization', async () => { expect(await oracleSTEUR.stalePeriod()).to.be.equal(stalePeriod); From e9ed41f6380a866b27b13c8e36f33c3a77ae1462 Mon Sep 17 00:00:00 2001 From: Pablo Veyrat Date: Thu, 25 Jan 2024 12:16:56 +0100 Subject: [PATCH 6/7] feat: add comment --- .../arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol b/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol index 64de0527..eedf4f05 100644 --- a/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol +++ b/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol @@ -52,7 +52,11 @@ contract OracleSTEURETHChainlinkArbitrum is BaseOracleChainlinkMultiTwoFeeds, Ag /// @return startedAt /// @return timestamp /// @return answeredInRound - /// @dev The roundId, startedAt and answeredInRound values return in this function must be disregarded + /// @dev The `roundId`, `startedAt` and `answeredInRound` values return in this function must be disregarded + /// @dev In order not to multiply oracle calls, the timestamp returned here is the `block.timestamp`. + /// The contract still performs an heartbeat check for every oracle value that it reads, and the accurate + /// value of the `timestamp` (if this one is taken as the minimum between the last update timestamp + /// of the two oracles) is between: current timestamp and the current timestamp minus `stalePeriod` function latestRoundData() public view returns (uint80, int256, uint256, uint256, uint80) { return (0, int256(read()), 0, block.timestamp, 0); } From 48eb840560eea23a653822530b894a73026aaa5c Mon Sep 17 00:00:00 2001 From: Pablo Veyrat Date: Thu, 25 Jan 2024 12:19:37 +0100 Subject: [PATCH 7/7] feat: add oracle --- .../EUR/OracleSTEURETHChainlinkArbitrum.sol | 5 + deployments/arbitrum/Oracle_STEUR_ETH.json | 384 ++++++++++++++++++ .../ee130155c0ce7c2eaa2c9a7b8d6f574f.json | 88 ++++ package.json | 2 +- 4 files changed, 478 insertions(+), 1 deletion(-) create mode 100644 deployments/arbitrum/Oracle_STEUR_ETH.json create mode 100644 deployments/arbitrum/solcInputs/ee130155c0ce7c2eaa2c9a7b8d6f574f.json diff --git a/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol b/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol index eedf4f05..ce220450 100644 --- a/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol +++ b/contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol @@ -35,18 +35,22 @@ contract OracleSTEURETHChainlinkArbitrum is BaseOracleChainlinkMultiTwoFeeds, Ag CHAINLINK INTERFACE COMPATIBILITY //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ + /// @inheritdoc AggregatorV3Interface function decimals() external pure returns (uint8) { return 18; } + /// @inheritdoc AggregatorV3Interface function description() external pure returns (string memory desc) { desc = "Angle stEUR/ETH Price Feed"; } + /// @inheritdoc AggregatorV3Interface function version() external pure returns (uint256) { return 1; } + /// @inheritdoc AggregatorV3Interface /// @return roundID /// @return aggregatorPrice /// @return startedAt @@ -61,6 +65,7 @@ contract OracleSTEURETHChainlinkArbitrum is BaseOracleChainlinkMultiTwoFeeds, Ag return (0, int256(read()), 0, block.timestamp, 0); } + /// @inheritdoc AggregatorV3Interface /// @dev This function always returns the latestRoundData function getRoundData(uint80) external view returns (uint80, int256, uint256, uint256, uint80) { return latestRoundData(); diff --git a/deployments/arbitrum/Oracle_STEUR_ETH.json b/deployments/arbitrum/Oracle_STEUR_ETH.json new file mode 100644 index 00000000..792a33ba --- /dev/null +++ b/deployments/arbitrum/Oracle_STEUR_ETH.json @@ -0,0 +1,384 @@ +{ + "address": "0x9418D0aa02fCE40804aBF77bb81a1CcBeB91eaFC", + "abi": [ + { + "inputs": [ + { + "internalType": "uint32", + "name": "_stalePeriod", + "type": "uint32" + }, + { + "internalType": "address", + "name": "_treasury", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidChainlinkRate", + "type": "error" + }, + { + "inputs": [], + "name": "NotGovernorOrGuardian", + "type": "error" + }, + { + "inputs": [], + "name": "NotVaultManagerOrGovernor", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "_stalePeriod", + "type": "uint32" + } + ], + "name": "StalePeriodUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "DESCRIPTION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STEUR", + "outputs": [ + { + "internalType": "contract IERC4626", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_stalePeriod", + "type": "uint32" + } + ], + "name": "changeStalePeriod", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "circuitChainlink", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "description", + "outputs": [ + { + "internalType": "string", + "name": "desc", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint80", + "name": "", + "type": "uint80" + } + ], + "name": "getRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "read", + "outputs": [ + { + "internalType": "uint256", + "name": "quoteAmount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_treasury", + "type": "address" + } + ], + "name": "setTreasury", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stalePeriod", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "treasury", + "outputs": [ + { + "internalType": "contract ITreasury", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0x3fac689e680cbe36fbbc676d13cebf06e047b407a6573e9e0722a649a6d66146", + "receipt": { + "to": null, + "from": "0xfdA462548Ce04282f4B6D6619823a7C64Fdc0185", + "contractAddress": "0x9418D0aa02fCE40804aBF77bb81a1CcBeB91eaFC", + "transactionIndex": 1, + "gasUsed": "11108754", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x33da5095b8f2c5167ee348073ffd20bf83e67a7cef29ba54551b0f43b568a33b", + "transactionHash": "0x3fac689e680cbe36fbbc676d13cebf06e047b407a6573e9e0722a649a6d66146", + "logs": [], + "blockNumber": 174017794, + "cumulativeGasUsed": "11108754", + "status": 1, + "byzantium": true + }, + "args": [ + 129600, + "0x0D710512E100C171139D2Cf5708f22C680eccF52" + ], + "numDeployments": 1, + "solcInputHash": "ee130155c0ce7c2eaa2c9a7b8d6f574f", + "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_stalePeriod\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"_treasury\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidChainlinkRate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotGovernorOrGuardian\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotVaultManagerOrGovernor\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"_stalePeriod\",\"type\":\"uint32\"}],\"name\":\"StalePeriodUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DESCRIPTION\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STEUR\",\"outputs\":[{\"internalType\":\"contract IERC4626\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_stalePeriod\",\"type\":\"uint32\"}],\"name\":\"changeStalePeriod\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"circuitChainlink\",\"outputs\":[{\"internalType\":\"contract AggregatorV3Interface[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"description\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"desc\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint80\",\"name\":\"\",\"type\":\"uint80\"}],\"name\":\"getRoundData\",\"outputs\":[{\"internalType\":\"uint80\",\"name\":\"\",\"type\":\"uint80\"},{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint80\",\"name\":\"\",\"type\":\"uint80\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestRoundData\",\"outputs\":[{\"internalType\":\"uint80\",\"name\":\"\",\"type\":\"uint80\"},{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint80\",\"name\":\"\",\"type\":\"uint80\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"read\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"quoteAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_treasury\",\"type\":\"address\"}],\"name\":\"setTreasury\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stalePeriod\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasury\",\"outputs\":[{\"internalType\":\"contract ITreasury\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Angle Labs, Inc.\",\"kind\":\"dev\",\"methods\":{\"changeStalePeriod(uint32)\":{\"params\":{\"_stalePeriod\":\"New stale period (in seconds)\"}},\"getRoundData(uint80)\":{\"details\":\"This function always returns the latestRoundData\"},\"latestRoundData()\":{\"details\":\"The `roundId`, `startedAt` and `answeredInRound` values return in this function must be disregardedIn order not to multiply oracle calls, the timestamp returned here is the `block.timestamp`. The contract still performs an heartbeat check for every oracle value that it reads, and the accurate value of the `timestamp` (if this one is taken as the minimum between the last update timestamp of the two oracles) is between: current timestamp and the current timestamp minus `stalePeriod`\",\"returns\":{\"_0\":\"roundID\",\"_1\":\"aggregatorPrice\",\"_2\":\"startedAt\",\"_3\":\"timestamp\",\"_4\":\"answeredInRound\"}},\"read()\":{\"details\":\"For instance if the out currency is EUR (and hence agEUR), then the base of the returned value is 10**18\",\"returns\":{\"quoteAmount\":\"The current rate between the in-currency and out-currency in the base of the out currency\"}},\"setTreasury(address)\":{\"details\":\"This function can be called by an approved `VaultManager` contract which can call this function after being requested to do so by a `treasury` contractIn some situations (like reactor contracts), the `VaultManager` may not directly be linked to the `oracle` contract and as such we may need governors to be able to call this function as well\",\"params\":{\"_treasury\":\"Address of the new treasury contract\"}}},\"title\":\"OracleSTEURETHChainlinkArbitrum\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"changeStalePeriod(uint32)\":{\"notice\":\"Changes the stale period\"},\"circuitChainlink()\":{\"notice\":\"Array with the list of Chainlink feeds in the order in which they are read\"},\"read()\":{\"notice\":\"Reads the rate from the Chainlink circuit and other data provided\"},\"setTreasury(address)\":{\"notice\":\"Changes the treasury contract\"},\"stalePeriod()\":{\"notice\":\"Represent the maximum amount of time (in seconds) between each Chainlink update before the price feed is considered stale\"},\"treasury()\":{\"notice\":\"Reference to the `treasury` contract handling this `VaultManager`\"}},\"notice\":\"Gives the price of stEUR in ETH in base 18\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol\":\"OracleSTEURETHChainlinkArbitrum\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[]},\"sources\":{\"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface AggregatorV3Interface {\\n\\n function decimals()\\n external\\n view\\n returns (\\n uint8\\n );\\n\\n function description()\\n external\\n view\\n returns (\\n string memory\\n );\\n\\n function version()\\n external\\n view\\n returns (\\n uint256\\n );\\n\\n // getRoundData and latestRoundData should both raise \\\"No data present\\\"\\n // if they do not have data to report, instead of returning unset values\\n // which could be misinterpreted as actual reported values.\\n function getRoundData(\\n uint80 _roundId\\n )\\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}\\n\",\"keccak256\":\"0xe6f5ac8c47f3b9b6135051efb9216f9ba5b312a6ecc20209b4f66a780443c328\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.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 IERC20Upgradeable {\\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(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4e733d3164f73f461eaf9d8087a7ad1ea180bdc8ba0d3d61b0e1ae16d8e63dff\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.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.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\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 * The default value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\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 value {ERC20} uses, unless this function is\\n * 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(\\n address from,\\n address to,\\n uint256 amount\\n ) 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(\\n address from,\\n address to,\\n uint256 amount\\n ) 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 }\\n _balances[to] += amount;\\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 _balances[account] += amount;\\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 }\\n _totalSupply -= amount;\\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(\\n address owner,\\n address spender,\\n uint256 amount\\n ) 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(\\n address owner,\\n address spender,\\n uint256 amount\\n ) 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(\\n address from,\\n address to,\\n uint256 amount\\n ) 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(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.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(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"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\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x032807210d1d7d218963d7355d62e021a84bf1b3339f4f50be2f63b53cccaf29\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.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 /// @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}\\n\",\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\"},\"@openzeppelin/contracts/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\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/interfaces/IAgToken.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.12;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\n/// @title IAgToken\\n/// @author Angle Labs, Inc.\\n/// @notice Interface for the stablecoins `AgToken` contracts\\n/// @dev This interface only contains functions of the `AgToken` contract which are called by other contracts\\n/// of this module or of the first module of the Angle Protocol\\ninterface IAgToken is IERC20Upgradeable {\\n // ======================= Minter Role Only Functions ===========================\\n\\n /// @notice Lets the `StableMaster` contract or another whitelisted contract mint agTokens\\n /// @param account Address to mint to\\n /// @param amount Amount to mint\\n /// @dev The contracts allowed to issue agTokens are the `StableMaster` contract, `VaultManager` contracts\\n /// associated to this stablecoin as well as the flash loan module (if activated) and potentially contracts\\n /// whitelisted by governance\\n function mint(address account, uint256 amount) external;\\n\\n /// @notice Burns `amount` tokens from a `burner` address after being asked to by `sender`\\n /// @param amount Amount of tokens to burn\\n /// @param burner Address to burn from\\n /// @param sender Address which requested the burn from `burner`\\n /// @dev This method is to be called by a contract with the minter right after being requested\\n /// to do so by a `sender` address willing to burn tokens from another `burner` address\\n /// @dev The method checks the allowance between the `sender` and the `burner`\\n function burnFrom(uint256 amount, address burner, address sender) external;\\n\\n /// @notice Burns `amount` tokens from a `burner` address\\n /// @param amount Amount of tokens to burn\\n /// @param burner Address to burn from\\n /// @dev This method is to be called by a contract with a minter right on the AgToken after being\\n /// requested to do so by an address willing to burn tokens from its address\\n function burnSelf(uint256 amount, address burner) external;\\n\\n // ========================= Treasury Only Functions ===========================\\n\\n /// @notice Adds a minter in the contract\\n /// @param minter Minter address to add\\n /// @dev Zero address checks are performed directly in the `Treasury` contract\\n function addMinter(address minter) external;\\n\\n /// @notice Removes a minter from the contract\\n /// @param minter Minter address to remove\\n /// @dev This function can also be called by a minter wishing to revoke itself\\n function removeMinter(address minter) external;\\n\\n /// @notice Sets a new treasury contract\\n /// @param _treasury New treasury address\\n function setTreasury(address _treasury) external;\\n\\n // ========================= External functions ================================\\n\\n /// @notice Checks whether an address has the right to mint agTokens\\n /// @param minter Address for which the minting right should be checked\\n /// @return Whether the address has the right to mint agTokens or not\\n function isMinter(address minter) external view returns (bool);\\n\\n /// @notice Get the associated treasury\\n function treasury() external view returns (address);\\n}\\n\",\"keccak256\":\"0x0c83efcfc1fb9ae9ba830f7b89e3dab9abf6ad7a6205a31aa35fbccaa837dcdc\",\"license\":\"GPL-3.0\"},\"contracts/interfaces/ICoreBorrow.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.12;\\n\\n/// @title ICoreBorrow\\n/// @author Angle Labs, Inc.\\n/// @notice Interface for the `CoreBorrow` contract\\n/// @dev This interface only contains functions of the `CoreBorrow` contract which are called by other contracts\\n/// of this module\\ninterface ICoreBorrow {\\n /// @notice Checks if an address corresponds to a treasury of a stablecoin with a flash loan\\n /// module initialized on it\\n /// @param treasury Address to check\\n /// @return Whether the address has the `FLASHLOANER_TREASURY_ROLE` or not\\n function isFlashLoanerTreasury(address treasury) external view returns (bool);\\n\\n /// @notice Checks whether an address is governor of the Angle Protocol or not\\n /// @param admin Address to check\\n /// @return Whether the address has the `GOVERNOR_ROLE` or not\\n function isGovernor(address admin) external view returns (bool);\\n\\n /// @notice Checks whether an address is governor or a guardian of the Angle Protocol or not\\n /// @param admin Address to check\\n /// @return Whether the address has the `GUARDIAN_ROLE` or not\\n /// @dev Governance should make sure when adding a governor to also give this governor the guardian\\n /// role by calling the `addGovernor` function\\n function isGovernorOrGuardian(address admin) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x10249210cbf522775f040baf981d7d037472168ce2746d87473ac7c29a34e62e\",\"license\":\"GPL-3.0\"},\"contracts/interfaces/IFlashAngle.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.12;\\n\\nimport \\\"./IAgToken.sol\\\";\\nimport \\\"./ICoreBorrow.sol\\\";\\n\\n/// @title IFlashAngle\\n/// @author Angle Labs, Inc.\\n/// @notice Interface for the `FlashAngle` contract\\n/// @dev This interface only contains functions of the contract which are called by other contracts\\n/// of this module\\ninterface IFlashAngle {\\n /// @notice Reference to the `CoreBorrow` contract managing the FlashLoan module\\n function core() external view returns (ICoreBorrow);\\n\\n /// @notice Sends the fees taken from flash loans to the treasury contract associated to the stablecoin\\n /// @param stablecoin Stablecoin from which profits should be sent\\n /// @return balance Amount of profits sent\\n /// @dev This function can only be called by the treasury contract\\n function accrueInterestToTreasury(IAgToken stablecoin) external returns (uint256 balance);\\n\\n /// @notice Adds support for a stablecoin\\n /// @param _treasury Treasury associated to the stablecoin to add support for\\n /// @dev This function can only be called by the `CoreBorrow` contract\\n function addStablecoinSupport(address _treasury) external;\\n\\n /// @notice Removes support for a stablecoin\\n /// @param _treasury Treasury associated to the stablecoin to remove support for\\n /// @dev This function can only be called by the `CoreBorrow` contract\\n function removeStablecoinSupport(address _treasury) external;\\n\\n /// @notice Sets a new core contract\\n /// @param _core Core contract address to set\\n /// @dev This function can only be called by the `CoreBorrow` contract\\n function setCore(address _core) external;\\n}\\n\",\"keccak256\":\"0x39b0097f695b9e934bccdc72676c91513f1077cc5d0fd151908fd25a7c5cfbe4\",\"license\":\"GPL-3.0\"},\"contracts/interfaces/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.12;\\n\\nimport \\\"./ITreasury.sol\\\";\\nimport \\\"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\\\";\\n\\n/// @title IOracle\\n/// @author Angle Labs, Inc.\\n/// @notice Interface for the `Oracle` contract\\n/// @dev This interface only contains functions of the contract which are called by other contracts\\n/// of this module\\ninterface IOracle {\\n /// @notice Reads the rate from the Chainlink circuit and other data provided\\n /// @return quoteAmount The current rate between the in-currency and out-currency in the base\\n /// of the out currency\\n /// @dev For instance if the out currency is EUR (and hence agEUR), then the base of the returned\\n /// value is 10**18\\n function read() external view returns (uint256);\\n\\n /// @notice Changes the treasury contract\\n /// @param _treasury Address of the new treasury contract\\n /// @dev This function can be called by an approved `VaultManager` contract which can call\\n /// this function after being requested to do so by a `treasury` contract\\n /// @dev In some situations (like reactor contracts), the `VaultManager` may not directly be linked\\n /// to the `oracle` contract and as such we may need governors to be able to call this function as well\\n function setTreasury(address _treasury) external;\\n\\n /// @notice Reference to the `treasury` contract handling this `VaultManager`\\n function treasury() external view returns (ITreasury treasury);\\n\\n /// @notice Array with the list of Chainlink feeds in the order in which they are read\\n function circuitChainlink() external view returns (AggregatorV3Interface[] memory);\\n}\\n\",\"keccak256\":\"0x66fe2bb27f26b86e5832fc7d1ebd320cac8b3d79c5998ce148cf7279b2b359be\",\"license\":\"GPL-3.0\"},\"contracts/interfaces/ITreasury.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.12;\\n\\nimport \\\"./IAgToken.sol\\\";\\nimport \\\"./ICoreBorrow.sol\\\";\\nimport \\\"./IFlashAngle.sol\\\";\\n\\n/// @title ITreasury\\n/// @author Angle Labs, Inc.\\n/// @notice Interface for the `Treasury` contract\\n/// @dev This interface only contains functions of the `Treasury` which are called by other contracts\\n/// of this module\\ninterface ITreasury {\\n /// @notice Stablecoin handled by this `treasury` contract\\n function stablecoin() external view returns (IAgToken);\\n\\n /// @notice Checks whether a given address has the governor role\\n /// @param admin Address to check\\n /// @return Whether the address has the governor role\\n /// @dev Access control is only kept in the `CoreBorrow` contract\\n function isGovernor(address admin) external view returns (bool);\\n\\n /// @notice Checks whether a given address has the guardian or the governor role\\n /// @param admin Address to check\\n /// @return Whether the address has the guardian or the governor role\\n /// @dev Access control is only kept in the `CoreBorrow` contract which means that this function\\n /// queries the `CoreBorrow` contract\\n function isGovernorOrGuardian(address admin) external view returns (bool);\\n\\n /// @notice Checks whether a given address has well been initialized in this contract\\n /// as a `VaultManager`\\n /// @param _vaultManager Address to check\\n /// @return Whether the address has been initialized or not\\n function isVaultManager(address _vaultManager) external view returns (bool);\\n\\n /// @notice Sets a new flash loan module for this stablecoin\\n /// @param _flashLoanModule Reference to the new flash loan module\\n /// @dev This function removes the minting right to the old flash loan module and grants\\n /// it to the new module\\n function setFlashLoanModule(address _flashLoanModule) external;\\n\\n /// @notice Gets the vault manager list\\n function vaultManagerList(uint256 i) external returns (address);\\n}\\n\",\"keccak256\":\"0x06c2f781c08732ce1b5845c083af5742716245baa6c519bd737f32b230a884c1\",\"license\":\"GPL-3.0\"},\"contracts/interfaces/external/IERC4626.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n/// @notice Minimal IERC4646 tokenized Vault interface.\\n/// @author Forked from Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/mixins/ERC4626.sol)\\n/// @dev Do not use in production! ERC-4626 is still in the review stage and is subject to change.\\ninterface IERC4626 {\\n event Deposit(address indexed from, address indexed to, uint256 amount, uint256 shares);\\n event Withdraw(address indexed from, address indexed to, uint256 amount, uint256 shares);\\n\\n /// @notice Transfers a given amount of asset to the reactor and mint shares accordingly\\n /// @param amount Given amount of asset\\n /// @param to Address to mint shares to\\n /// @return shares Amount of shares minted to `to`\\n function deposit(uint256 amount, address to) external returns (uint256 shares);\\n\\n /// @notice Mints a given amount of shares to the reactor and transfer assets accordingly\\n /// @param shares Given amount of shares\\n /// @param to Address to mint shares to\\n /// @return amount Amount of `asset` taken to the `msg.sender` to mint `shares`\\n function mint(uint256 shares, address to) external returns (uint256 amount);\\n\\n /// @notice Transfers a given amount of asset from the reactor and burn shares accordingly\\n /// @param amount Given amount of asset\\n /// @param to Address to transfer assets to\\n /// @param from Address to burn shares from\\n /// @return shares Amount of shares burnt in the operation\\n function withdraw(uint256 amount, address to, address from) external returns (uint256 shares);\\n\\n /// @notice Burns a given amount of shares to the reactor and transfer assets accordingly\\n /// @param shares Given amount of shares\\n /// @param to Address to transfer assets to\\n /// @param from Address to burn shares from\\n /// @return amount Amount of assets redeemed in the operation\\n function redeem(uint256 shares, address to, address from) external returns (uint256 amount);\\n\\n /// @notice Returns the total assets managed by this reactor\\n function totalAssets() external view returns (uint256);\\n\\n /// @notice Converts an amount of assets to the corresponding amount of reactor shares\\n /// @param assets Amount of asset to convert\\n /// @return Shares corresponding to the amount of assets obtained\\n function convertToShares(uint256 assets) external view returns (uint256);\\n\\n /// @notice Converts an amount of shares to its current value in asset\\n /// @param shares Amount of shares to convert\\n /// @return Amount of assets corresponding to the amount of assets given\\n function convertToAssets(uint256 shares) external view returns (uint256);\\n\\n /// @notice Computes how many shares one would get by depositing `assets`\\n /// @param assets Amount of asset to convert\\n function previewDeposit(uint256 assets) external view returns (uint256);\\n\\n /// @notice Computes how many assets one would need to mint `shares`\\n /// @param shares Amount of shares required\\n function previewMint(uint256 shares) external view returns (uint256);\\n\\n /// @notice Computes how many shares one would need to withdraw assets\\n /// @param assets Amount of asset to withdraw\\n function previewWithdraw(uint256 assets) external view returns (uint256);\\n\\n /// @notice Computes how many assets one would get by burning shares\\n /// @param shares Amount of shares to burn\\n function previewRedeem(uint256 shares) external view returns (uint256);\\n\\n /// @notice Max deposit allowed for a user\\n /// @param user Address of the user to check\\n function maxDeposit(address user) external returns (uint256);\\n\\n /// @notice Max mint allowed for a user\\n /// @param user Address of the user to check\\n function maxMint(address user) external returns (uint256);\\n\\n /// @notice Max withdraw allowed for a user\\n /// @param user Address of the user to check\\n function maxWithdraw(address user) external returns (uint256);\\n\\n /// @notice Max redeem allowed for a user\\n /// @param user Address of the user to check\\n function maxRedeem(address user) external returns (uint256);\\n}\\n\",\"keccak256\":\"0x34aa284314d37ee7e1b3da7457425ed9fed2b8f95d01ced78ba4bef4b3c9c9c6\",\"license\":\"AGPL-3.0-only\"},\"contracts/oracle/BaseOracleChainlinkMulti.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\n/*\\n * \\u2588 \\n ***** \\u2593\\u2593\\u2593 \\n * \\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593 \\n * ///. \\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593 \\n ***** //////// \\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593 \\n * ///////////// \\u2593\\u2593\\u2593 \\n \\u2593\\u2593 ////////////////// \\u2588 \\u2593\\u2593 \\n \\u2593\\u2593 \\u2593\\u2593 /////////////////////// \\u2593\\u2593 \\u2593\\u2593 \\n \\u2593\\u2593 \\u2593\\u2593 //////////////////////////// \\u2593\\u2593 \\u2593\\u2593 \\n \\u2593\\u2593 \\u2593\\u2593 /////////\\u2593\\u2593\\u2593///////\\u2593\\u2593\\u2593///////// \\u2593\\u2593 \\u2593\\u2593 \\n \\u2593\\u2593 ,////////////////////////////////////// \\u2593\\u2593 \\u2593\\u2593 \\n \\u2593\\u2593 ////////////////////////////////////////// \\u2593\\u2593 \\n \\u2593\\u2593 //////////////////////\\u2593\\u2593\\u2593\\u2593///////////////////// \\n ,//////////////////////////////////////////////////// \\n .////////////////////////////////////////////////////////// \\n .//////////////////////////\\u2588\\u2588.,//////////////////////////\\u2588 \\n .//////////////////////\\u2588\\u2588\\u2588\\u2588..,./////////////////////\\u2588\\u2588 \\n ...////////////////\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588.....,.////////////////\\u2588\\u2588\\u2588 \\n ,.,////////////\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588 ........,///////////\\u2588\\u2588\\u2588\\u2588 \\n .,.,//////\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588 ,.......///////\\u2588\\u2588\\u2588\\u2588 \\n ,..//\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588 ........./\\u2588\\u2588\\u2588\\u2588 \\n ..,\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588 .....,\\u2588\\u2588\\u2588 \\n .\\u2588\\u2588 ,.,\\u2588 \\n \\n \\n \\n \\u2593\\u2593 \\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593 \\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593 \\u2593\\u2593 \\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593 \\n \\u2593\\u2593\\u2593\\u2593\\u2593\\u2593 \\u2593\\u2593\\u2593 \\u2593\\u2593\\u2593 \\u2593\\u2593\\u2593 \\u2593\\u2593 \\u2593\\u2593 \\u2593\\u2593\\u2593\\u2593 \\n \\u2593\\u2593\\u2593 \\u2593\\u2593\\u2593 \\u2593\\u2593\\u2593 \\u2593\\u2593\\u2593 \\u2593\\u2593\\u2593 \\u2593\\u2593\\u2593 \\u2593\\u2593 \\u2593\\u2593\\u2593\\u2593\\u2593 \\n \\u2593\\u2593\\u2593 \\u2593\\u2593 \\u2593\\u2593\\u2593 \\u2593\\u2593\\u2593 \\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593 \\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593 \\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593\\u2593 \\n*/\\n\\npragma solidity ^0.8.12;\\n\\nimport \\\"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\\\";\\n\\nimport \\\"../interfaces/IOracle.sol\\\";\\nimport \\\"../interfaces/ITreasury.sol\\\";\\n\\n/// @title BaseOracleChainlinkMulti\\n/// @author Angle Labs, Inc.\\n/// @notice Base Contract to be overriden by all contracts of the protocol\\n/// @dev This base contract concerns an oracle that uses Chainlink with multiple pools to read from\\n/// @dev All gas-efficient implementation of the `OracleChainlinkMulti` contract should inherit from this\\nabstract contract BaseOracleChainlinkMulti is IOracle {\\n // ========================= Parameters and References =========================\\n\\n /// @inheritdoc IOracle\\n ITreasury public override treasury;\\n /// @notice Represent the maximum amount of time (in seconds) between each Chainlink update\\n /// before the price feed is considered stale\\n uint32 public stalePeriod;\\n\\n // =================================== Event ===================================\\n\\n event StalePeriodUpdated(uint32 _stalePeriod);\\n\\n // =================================== Errors ===================================\\n\\n error InvalidChainlinkRate();\\n error NotGovernorOrGuardian();\\n error NotVaultManagerOrGovernor();\\n\\n /// @notice Constructor for an oracle using Chainlink with multiple pools to read from\\n /// @param _stalePeriod Minimum feed update frequency for the oracle to not revert\\n /// @param _treasury Treasury associated to the VaultManager which reads from this feed\\n constructor(uint32 _stalePeriod, address _treasury) {\\n stalePeriod = _stalePeriod;\\n treasury = ITreasury(_treasury);\\n }\\n\\n // ============================= Reading Oracles ===============================\\n\\n /// @inheritdoc IOracle\\n function read() external view virtual override returns (uint256 quoteAmount);\\n\\n /// @inheritdoc IOracle\\n function circuitChainlink() public view virtual returns (AggregatorV3Interface[] memory);\\n\\n /// @notice Reads a Chainlink feed using a quote amount and converts the quote amount to\\n /// the out-currency\\n /// @param quoteAmount The amount for which to compute the price expressed with base decimal\\n /// @param feed Chainlink feed to query\\n /// @param multiplied Whether the ratio outputted by Chainlink should be multiplied or divided\\n /// to the `quoteAmount`\\n /// @param decimals Number of decimals of the corresponding Chainlink pair\\n /// @return The `quoteAmount` converted in out-currency\\n function _readChainlinkFeed(\\n uint256 quoteAmount,\\n AggregatorV3Interface feed,\\n uint8 multiplied,\\n uint256 decimals\\n ) internal view returns (uint256) {\\n (uint80 roundId, int256 ratio, , uint256 updatedAt, uint80 answeredInRound) = feed.latestRoundData();\\n if (ratio <= 0 || roundId > answeredInRound || block.timestamp - updatedAt > stalePeriod)\\n revert InvalidChainlinkRate();\\n uint256 castedRatio = uint256(ratio);\\n // Checking whether we should multiply or divide by the ratio computed\\n if (multiplied == 1) return (quoteAmount * castedRatio) / (10 ** decimals);\\n else return (quoteAmount * (10 ** decimals)) / castedRatio;\\n }\\n\\n // ======================= Governance Related Functions ========================\\n\\n /// @notice Changes the stale period\\n /// @param _stalePeriod New stale period (in seconds)\\n function changeStalePeriod(uint32 _stalePeriod) external {\\n if (!treasury.isGovernorOrGuardian(msg.sender)) revert NotGovernorOrGuardian();\\n stalePeriod = _stalePeriod;\\n emit StalePeriodUpdated(_stalePeriod);\\n }\\n\\n /// @inheritdoc IOracle\\n function setTreasury(address _treasury) external override {\\n if (!treasury.isVaultManager(msg.sender) && !treasury.isGovernor(msg.sender))\\n revert NotVaultManagerOrGovernor();\\n treasury = ITreasury(_treasury);\\n }\\n}\\n\",\"keccak256\":\"0x6dc796277e844596455ea6d486fd5d439e407688ba4573055ab0b61c924588ed\",\"license\":\"GPL-3.0\"},\"contracts/oracle/BaseOracleChainlinkMultiTwoFeeds.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.12;\\n\\nimport \\\"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\\\";\\n\\nimport \\\"./BaseOracleChainlinkMulti.sol\\\";\\n\\n/// @title BaseOracleChainlinkMultiTwoFeeds\\n/// @author Angle Labs, Inc.\\n/// @notice Base contract for an oracle that reads into two Chainlink feeds (including an EUR/USD feed) which both have\\n/// 8 decimals\\nabstract contract BaseOracleChainlinkMultiTwoFeeds is BaseOracleChainlinkMulti {\\n constructor(uint32 _stalePeriod, address _treasury) BaseOracleChainlinkMulti(_stalePeriod, _treasury) {}\\n\\n /// @notice Returns the quote amount of the oracle contract\\n function _getQuoteAmount() internal view virtual returns (uint256) {\\n return 10 ** 18;\\n }\\n\\n /// @inheritdoc IOracle\\n function read() public view virtual override returns (uint256 quoteAmount) {\\n quoteAmount = _getQuoteAmount();\\n AggregatorV3Interface[] memory _circuitChainlink = circuitChainlink();\\n uint8[2] memory circuitChainIsMultiplied = [1, 0];\\n uint8[2] memory chainlinkDecimals = [8, 8];\\n uint256 circuitLength = _circuitChainlink.length;\\n for (uint256 i; i < circuitLength; ++i) {\\n quoteAmount = _readChainlinkFeed(\\n quoteAmount,\\n _circuitChainlink[i],\\n circuitChainIsMultiplied[i],\\n chainlinkDecimals[i]\\n );\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf88cf97ce509faa5de885a71f997a852b082721e921f39f25c02f0391816c42b\",\"license\":\"GPL-3.0\"},\"contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.12;\\n\\nimport \\\"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\\\";\\n\\nimport \\\"../../../BaseOracleChainlinkMultiTwoFeeds.sol\\\";\\nimport \\\"../../../../interfaces/external/IERC4626.sol\\\";\\n\\n/// @title OracleSTEURETHChainlinkArbitrum\\n/// @author Angle Labs, Inc.\\n/// @notice Gives the price of stEUR in ETH in base 18\\ncontract OracleSTEURETHChainlinkArbitrum is BaseOracleChainlinkMultiTwoFeeds, AggregatorV3Interface {\\n string public constant DESCRIPTION = \\\"stEUR/ETH Oracle\\\";\\n IERC4626 public constant STEUR = IERC4626(0x004626A008B1aCdC4c74ab51644093b155e59A23);\\n\\n constructor(uint32 _stalePeriod, address _treasury) BaseOracleChainlinkMultiTwoFeeds(_stalePeriod, _treasury) {}\\n\\n /// @inheritdoc IOracle\\n function circuitChainlink() public pure override returns (AggregatorV3Interface[] memory) {\\n AggregatorV3Interface[] memory _circuitChainlink = new AggregatorV3Interface[](2);\\n // Oracle agEUR/USD - Redstone\\n _circuitChainlink[0] = AggregatorV3Interface(0x37963F10245e7c3a10c0E9d43a6E617B4Bc8440A);\\n // Oracle ETH/USD - Chainlink\\n _circuitChainlink[1] = AggregatorV3Interface(0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612);\\n return _circuitChainlink;\\n }\\n\\n /// @inheritdoc BaseOracleChainlinkMultiTwoFeeds\\n function _getQuoteAmount() internal view override returns (uint256) {\\n return STEUR.convertToAssets(1 ether);\\n }\\n\\n /*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\\n CHAINLINK INTERFACE COMPATIBILITY \\n //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/\\n\\n /// @inheritdoc AggregatorV3Interface\\n function decimals() external pure returns (uint8) {\\n return 18;\\n }\\n\\n /// @inheritdoc AggregatorV3Interface\\n function description() external pure returns (string memory desc) {\\n desc = \\\"Angle stEUR/ETH Price Feed\\\";\\n }\\n\\n /// @inheritdoc AggregatorV3Interface\\n function version() external pure returns (uint256) {\\n return 1;\\n }\\n\\n /// @inheritdoc AggregatorV3Interface\\n /// @return roundID\\n /// @return aggregatorPrice\\n /// @return startedAt\\n /// @return timestamp\\n /// @return answeredInRound\\n /// @dev The `roundId`, `startedAt` and `answeredInRound` values return in this function must be disregarded\\n /// @dev In order not to multiply oracle calls, the timestamp returned here is the `block.timestamp`.\\n /// The contract still performs an heartbeat check for every oracle value that it reads, and the accurate\\n /// value of the `timestamp` (if this one is taken as the minimum between the last update timestamp\\n /// of the two oracles) is between: current timestamp and the current timestamp minus `stalePeriod`\\n function latestRoundData() public view returns (uint80, int256, uint256, uint256, uint80) {\\n return (0, int256(read()), 0, block.timestamp, 0);\\n }\\n\\n /// @inheritdoc AggregatorV3Interface\\n /// @dev This function always returns the latestRoundData\\n function getRoundData(uint80) external view returns (uint80, int256, uint256, uint256, uint80) {\\n return latestRoundData();\\n }\\n}\\n\",\"keccak256\":\"0x0f543d813fe19dcb62cb891799eee3ba23cd3310270b2d65dd0288631e0b6fb5\",\"license\":\"GPL-3.0\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50604051610eb4380380610eb483398101604081905261002f91610071565b600080546001600160c01b031916600160a01b63ffffffff94909416939093026001600160a01b031916929092176001600160a01b03919091161790556100c0565b6000806040838503121561008457600080fd5b825163ffffffff8116811461009857600080fd5b60208401519092506001600160a01b03811681146100b557600080fd5b809150509250929050565b610de5806100cf6000396000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c80637284e4161161008c578063a5b36a3611610066578063a5b36a3614610226578063f0f4426014610263578063f1ae885614610276578063feaf968c146102b257600080fd5b80637284e416146101805780637ce5e35e146101c25780639a6fc8f5146101dc57600080fd5b806357de26a4116100bd57806357de26a41461011e57806361d027b314610126578063630914d11461016b57600080fd5b8063313ce567146100e45780634994cc67146100f857806354fd4d501461010d575b600080fd5b604051601281526020015b60405180910390f35b6101006102ba565b6040516100ef919061098e565b60015b6040519081526020016100ef565b610110610393565b6000546101469073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ef565b61017e6101793660046109e8565b610450565b005b60408051808201909152601a81527f416e676c652073744555522f455448205072696365204665656400000000000060208201525b6040516100ef9190610a15565b610146724626a008b1acdc4c74ab51644093b155e59a2381565b6101ef6101ea366004610a9c565b61059b565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a0016100ef565b60005461024e9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016100ef565b61017e610271366004610ab9565b6105bd565b6101b56040518060400160405280601081526020017f73744555522f455448204f7261636c650000000000000000000000000000000081525081565b6101ef610769565b604080516002808252606080830184529260009291906020830190803683370190505090507337963f10245e7c3a10c0e9d43a6e617b4bc8440a8160008151811061030757610307610aef565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073639fe6ab55c921f74e7fac1ee960c0b6293ba6128160018151811061036957610369610aef565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152919050565b600061039d61078d565b905060006103a96102ba565b6040805180820182526001815260006020808301829052835180850190945260088085529084015283519394509092905b8181101561044857610436868683815181106103f8576103f8610aef565b602002602001015186846002811061041257610412610aef565b602002015186856002811061042957610429610aef565b602002015160ff16610828565b955061044181610b4d565b90506103da565b505050505090565b6000546040517f521d4de900000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091169063521d4de990602401602060405180830381865afa1580156104be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e29190610b85565b610518576040517f99e120bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000063ffffffff8416908102919091179091556040519081527f4040b15332969bfd8b2035c1a701c8e13f2b5d62ce89b311684a601b2eb44e019060200160405180910390a150565b60008060008060006105ab610769565b939a9299509097509550909350915050565b6000546040517f676a553e00000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091169063676a553e90602401602060405180830381865afa15801561062b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064f9190610b85565b1580156106eb57506000546040517fe43581b800000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091169063e43581b890602401602060405180830381865afa1580156106c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e99190610b85565b155b15610722576040517fb05b9b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60008060008060008061077a610393565b9096909550600094504293508492509050565b6040517f07a2d13a000000000000000000000000000000000000000000000000000000008152670de0b6b3a76400006004820152600090724626a008b1acdc4c74ab51644093b155e59a23906307a2d13a90602401602060405180830381865afa1580156107ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108239190610ba7565b905090565b60008060008060008773ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561087b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089f9190610bc0565b9450945050935093506000831315806108cf57508069ffffffffffffffffffff168469ffffffffffffffffffff16115b80610902575060005474010000000000000000000000000000000000000000900463ffffffff166109008342610c18565b115b15610939576040517fae19356300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260ff88166001036109705761095087600a610d51565b61095a828c610d5d565b6109649190610d74565b95505050505050610986565b8061097c88600a610d51565b61095a908c610d5d565b949350505050565b6020808252825182820181905260009190848201906040850190845b818110156109dc57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016109aa565b50909695505050505050565b6000602082840312156109fa57600080fd5b813563ffffffff81168114610a0e57600080fd5b9392505050565b600060208083528351808285015260005b81811015610a4257858101830151858201604001528201610a26565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b69ffffffffffffffffffff81168114610a9957600080fd5b50565b600060208284031215610aae57600080fd5b8135610a0e81610a81565b600060208284031215610acb57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610a0e57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610b7e57610b7e610b1e565b5060010190565b600060208284031215610b9757600080fd5b81518015158114610a0e57600080fd5b600060208284031215610bb957600080fd5b5051919050565b600080600080600060a08688031215610bd857600080fd5b8551610be381610a81565b809550506020860151935060408601519250606086015191506080860151610c0a81610a81565b809150509295509295909350565b81810381811115610c2b57610c2b610b1e565b92915050565b600181815b80851115610c8a57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610c7057610c70610b1e565b80851615610c7d57918102915b93841c9390800290610c36565b509250929050565b600082610ca157506001610c2b565b81610cae57506000610c2b565b8160018114610cc45760028114610cce57610cea565b6001915050610c2b565b60ff841115610cdf57610cdf610b1e565b50506001821b610c2b565b5060208310610133831016604e8410600b8410161715610d0d575081810a610c2b565b610d178383610c31565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610d4957610d49610b1e565b029392505050565b6000610a0e8383610c92565b8082028115828204841417610c2b57610c2b610b1e565b600082610daa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea2646970667358221220d21f9e764662be56e36d33b2e26fdecd6e4a0d13879f4a020992c4cdfdbfeb1d64736f6c63430008110033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100df5760003560e01c80637284e4161161008c578063a5b36a3611610066578063a5b36a3614610226578063f0f4426014610263578063f1ae885614610276578063feaf968c146102b257600080fd5b80637284e416146101805780637ce5e35e146101c25780639a6fc8f5146101dc57600080fd5b806357de26a4116100bd57806357de26a41461011e57806361d027b314610126578063630914d11461016b57600080fd5b8063313ce567146100e45780634994cc67146100f857806354fd4d501461010d575b600080fd5b604051601281526020015b60405180910390f35b6101006102ba565b6040516100ef919061098e565b60015b6040519081526020016100ef565b610110610393565b6000546101469073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ef565b61017e6101793660046109e8565b610450565b005b60408051808201909152601a81527f416e676c652073744555522f455448205072696365204665656400000000000060208201525b6040516100ef9190610a15565b610146724626a008b1acdc4c74ab51644093b155e59a2381565b6101ef6101ea366004610a9c565b61059b565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a0016100ef565b60005461024e9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016100ef565b61017e610271366004610ab9565b6105bd565b6101b56040518060400160405280601081526020017f73744555522f455448204f7261636c650000000000000000000000000000000081525081565b6101ef610769565b604080516002808252606080830184529260009291906020830190803683370190505090507337963f10245e7c3a10c0e9d43a6e617b4bc8440a8160008151811061030757610307610aef565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073639fe6ab55c921f74e7fac1ee960c0b6293ba6128160018151811061036957610369610aef565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152919050565b600061039d61078d565b905060006103a96102ba565b6040805180820182526001815260006020808301829052835180850190945260088085529084015283519394509092905b8181101561044857610436868683815181106103f8576103f8610aef565b602002602001015186846002811061041257610412610aef565b602002015186856002811061042957610429610aef565b602002015160ff16610828565b955061044181610b4d565b90506103da565b505050505090565b6000546040517f521d4de900000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091169063521d4de990602401602060405180830381865afa1580156104be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e29190610b85565b610518576040517f99e120bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000063ffffffff8416908102919091179091556040519081527f4040b15332969bfd8b2035c1a701c8e13f2b5d62ce89b311684a601b2eb44e019060200160405180910390a150565b60008060008060006105ab610769565b939a9299509097509550909350915050565b6000546040517f676a553e00000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091169063676a553e90602401602060405180830381865afa15801561062b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064f9190610b85565b1580156106eb57506000546040517fe43581b800000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091169063e43581b890602401602060405180830381865afa1580156106c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e99190610b85565b155b15610722576040517fb05b9b9f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60008060008060008061077a610393565b9096909550600094504293508492509050565b6040517f07a2d13a000000000000000000000000000000000000000000000000000000008152670de0b6b3a76400006004820152600090724626a008b1acdc4c74ab51644093b155e59a23906307a2d13a90602401602060405180830381865afa1580156107ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108239190610ba7565b905090565b60008060008060008773ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561087b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089f9190610bc0565b9450945050935093506000831315806108cf57508069ffffffffffffffffffff168469ffffffffffffffffffff16115b80610902575060005474010000000000000000000000000000000000000000900463ffffffff166109008342610c18565b115b15610939576040517fae19356300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260ff88166001036109705761095087600a610d51565b61095a828c610d5d565b6109649190610d74565b95505050505050610986565b8061097c88600a610d51565b61095a908c610d5d565b949350505050565b6020808252825182820181905260009190848201906040850190845b818110156109dc57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016109aa565b50909695505050505050565b6000602082840312156109fa57600080fd5b813563ffffffff81168114610a0e57600080fd5b9392505050565b600060208083528351808285015260005b81811015610a4257858101830151858201604001528201610a26565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b69ffffffffffffffffffff81168114610a9957600080fd5b50565b600060208284031215610aae57600080fd5b8135610a0e81610a81565b600060208284031215610acb57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610a0e57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610b7e57610b7e610b1e565b5060010190565b600060208284031215610b9757600080fd5b81518015158114610a0e57600080fd5b600060208284031215610bb957600080fd5b5051919050565b600080600080600060a08688031215610bd857600080fd5b8551610be381610a81565b809550506020860151935060408601519250606086015191506080860151610c0a81610a81565b809150509295509295909350565b81810381811115610c2b57610c2b610b1e565b92915050565b600181815b80851115610c8a57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610c7057610c70610b1e565b80851615610c7d57918102915b93841c9390800290610c36565b509250929050565b600082610ca157506001610c2b565b81610cae57506000610c2b565b8160018114610cc45760028114610cce57610cea565b6001915050610c2b565b60ff841115610cdf57610cdf610b1e565b50506001821b610c2b565b5060208310610133831016604e8410600b8410161715610d0d575081810a610c2b565b610d178383610c31565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610d4957610d49610b1e565b029392505050565b6000610a0e8383610c92565b8082028115828204841417610c2b57610c2b610b1e565b600082610daa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea2646970667358221220d21f9e764662be56e36d33b2e26fdecd6e4a0d13879f4a020992c4cdfdbfeb1d64736f6c63430008110033", + "devdoc": { + "author": "Angle Labs, Inc.", + "kind": "dev", + "methods": { + "changeStalePeriod(uint32)": { + "params": { + "_stalePeriod": "New stale period (in seconds)" + } + }, + "getRoundData(uint80)": { + "details": "This function always returns the latestRoundData" + }, + "latestRoundData()": { + "details": "The `roundId`, `startedAt` and `answeredInRound` values return in this function must be disregardedIn order not to multiply oracle calls, the timestamp returned here is the `block.timestamp`. The contract still performs an heartbeat check for every oracle value that it reads, and the accurate value of the `timestamp` (if this one is taken as the minimum between the last update timestamp of the two oracles) is between: current timestamp and the current timestamp minus `stalePeriod`", + "returns": { + "_0": "roundID", + "_1": "aggregatorPrice", + "_2": "startedAt", + "_3": "timestamp", + "_4": "answeredInRound" + } + }, + "read()": { + "details": "For instance if the out currency is EUR (and hence agEUR), then the base of the returned value is 10**18", + "returns": { + "quoteAmount": "The current rate between the in-currency and out-currency in the base of the out currency" + } + }, + "setTreasury(address)": { + "details": "This function can be called by an approved `VaultManager` contract which can call this function after being requested to do so by a `treasury` contractIn some situations (like reactor contracts), the `VaultManager` may not directly be linked to the `oracle` contract and as such we may need governors to be able to call this function as well", + "params": { + "_treasury": "Address of the new treasury contract" + } + } + }, + "title": "OracleSTEURETHChainlinkArbitrum", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "changeStalePeriod(uint32)": { + "notice": "Changes the stale period" + }, + "circuitChainlink()": { + "notice": "Array with the list of Chainlink feeds in the order in which they are read" + }, + "read()": { + "notice": "Reads the rate from the Chainlink circuit and other data provided" + }, + "setTreasury(address)": { + "notice": "Changes the treasury contract" + }, + "stalePeriod()": { + "notice": "Represent the maximum amount of time (in seconds) between each Chainlink update before the price feed is considered stale" + }, + "treasury()": { + "notice": "Reference to the `treasury` contract handling this `VaultManager`" + } + }, + "notice": "Gives the price of stEUR in ETH in base 18", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 1833, + "contract": "contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol:OracleSTEURETHChainlinkArbitrum", + "label": "treasury", + "offset": 0, + "slot": "0", + "type": "t_contract(ITreasury)1664" + }, + { + "astId": 1836, + "contract": "contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol:OracleSTEURETHChainlinkArbitrum", + "label": "stalePeriod", + "offset": 20, + "slot": "0", + "type": "t_uint32" + } + ], + "types": { + "t_contract(ITreasury)1664": { + "encoding": "inplace", + "label": "contract ITreasury", + "numberOfBytes": "20" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrum/solcInputs/ee130155c0ce7c2eaa2c9a7b8d6f574f.json b/deployments/arbitrum/solcInputs/ee130155c0ce7c2eaa2c9a7b8d6f574f.json new file mode 100644 index 00000000..938340bd --- /dev/null +++ b/deployments/arbitrum/solcInputs/ee130155c0ce7c2eaa2c9a7b8d6f574f.json @@ -0,0 +1,88 @@ +{ + "language": "Solidity", + "sources": { + "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n\n function decimals()\n external\n view\n returns (\n uint8\n );\n\n function description()\n external\n view\n returns (\n string memory\n );\n\n function version()\n external\n view\n returns (\n uint256\n );\n\n // getRoundData and latestRoundData should both raise \"No data present\"\n // if they do not have data to report, instead of returning unset values\n // which could be misinterpreted as actual reported values.\n function getRoundData(\n uint80 _roundId\n )\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}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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 IERC20Upgradeable {\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(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\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 * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\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 value {ERC20} uses, unless this function is\n * 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(\n address from,\n address to,\n uint256 amount\n ) 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(\n address from,\n address to,\n uint256 amount\n ) 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 }\n _balances[to] += amount;\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 _balances[account] += amount;\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 }\n _totalSupply -= amount;\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(\n address owner,\n address spender,\n uint256 amount\n ) 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(\n address owner,\n address spender,\n uint256 amount\n ) 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(\n address from,\n address to,\n uint256 amount\n ) 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(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\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.6.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(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 /// @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}\n" + }, + "@openzeppelin/contracts/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" + }, + "contracts/interfaces/external/IERC4626.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/// @notice Minimal IERC4646 tokenized Vault interface.\n/// @author Forked from Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/mixins/ERC4626.sol)\n/// @dev Do not use in production! ERC-4626 is still in the review stage and is subject to change.\ninterface IERC4626 {\n event Deposit(address indexed from, address indexed to, uint256 amount, uint256 shares);\n event Withdraw(address indexed from, address indexed to, uint256 amount, uint256 shares);\n\n /// @notice Transfers a given amount of asset to the reactor and mint shares accordingly\n /// @param amount Given amount of asset\n /// @param to Address to mint shares to\n /// @return shares Amount of shares minted to `to`\n function deposit(uint256 amount, address to) external returns (uint256 shares);\n\n /// @notice Mints a given amount of shares to the reactor and transfer assets accordingly\n /// @param shares Given amount of shares\n /// @param to Address to mint shares to\n /// @return amount Amount of `asset` taken to the `msg.sender` to mint `shares`\n function mint(uint256 shares, address to) external returns (uint256 amount);\n\n /// @notice Transfers a given amount of asset from the reactor and burn shares accordingly\n /// @param amount Given amount of asset\n /// @param to Address to transfer assets to\n /// @param from Address to burn shares from\n /// @return shares Amount of shares burnt in the operation\n function withdraw(uint256 amount, address to, address from) external returns (uint256 shares);\n\n /// @notice Burns a given amount of shares to the reactor and transfer assets accordingly\n /// @param shares Given amount of shares\n /// @param to Address to transfer assets to\n /// @param from Address to burn shares from\n /// @return amount Amount of assets redeemed in the operation\n function redeem(uint256 shares, address to, address from) external returns (uint256 amount);\n\n /// @notice Returns the total assets managed by this reactor\n function totalAssets() external view returns (uint256);\n\n /// @notice Converts an amount of assets to the corresponding amount of reactor shares\n /// @param assets Amount of asset to convert\n /// @return Shares corresponding to the amount of assets obtained\n function convertToShares(uint256 assets) external view returns (uint256);\n\n /// @notice Converts an amount of shares to its current value in asset\n /// @param shares Amount of shares to convert\n /// @return Amount of assets corresponding to the amount of assets given\n function convertToAssets(uint256 shares) external view returns (uint256);\n\n /// @notice Computes how many shares one would get by depositing `assets`\n /// @param assets Amount of asset to convert\n function previewDeposit(uint256 assets) external view returns (uint256);\n\n /// @notice Computes how many assets one would need to mint `shares`\n /// @param shares Amount of shares required\n function previewMint(uint256 shares) external view returns (uint256);\n\n /// @notice Computes how many shares one would need to withdraw assets\n /// @param assets Amount of asset to withdraw\n function previewWithdraw(uint256 assets) external view returns (uint256);\n\n /// @notice Computes how many assets one would get by burning shares\n /// @param shares Amount of shares to burn\n function previewRedeem(uint256 shares) external view returns (uint256);\n\n /// @notice Max deposit allowed for a user\n /// @param user Address of the user to check\n function maxDeposit(address user) external returns (uint256);\n\n /// @notice Max mint allowed for a user\n /// @param user Address of the user to check\n function maxMint(address user) external returns (uint256);\n\n /// @notice Max withdraw allowed for a user\n /// @param user Address of the user to check\n function maxWithdraw(address user) external returns (uint256);\n\n /// @notice Max redeem allowed for a user\n /// @param user Address of the user to check\n function maxRedeem(address user) external returns (uint256);\n}\n" + }, + "contracts/interfaces/IAgToken.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.12;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\n/// @title IAgToken\n/// @author Angle Labs, Inc.\n/// @notice Interface for the stablecoins `AgToken` contracts\n/// @dev This interface only contains functions of the `AgToken` contract which are called by other contracts\n/// of this module or of the first module of the Angle Protocol\ninterface IAgToken is IERC20Upgradeable {\n // ======================= Minter Role Only Functions ===========================\n\n /// @notice Lets the `StableMaster` contract or another whitelisted contract mint agTokens\n /// @param account Address to mint to\n /// @param amount Amount to mint\n /// @dev The contracts allowed to issue agTokens are the `StableMaster` contract, `VaultManager` contracts\n /// associated to this stablecoin as well as the flash loan module (if activated) and potentially contracts\n /// whitelisted by governance\n function mint(address account, uint256 amount) external;\n\n /// @notice Burns `amount` tokens from a `burner` address after being asked to by `sender`\n /// @param amount Amount of tokens to burn\n /// @param burner Address to burn from\n /// @param sender Address which requested the burn from `burner`\n /// @dev This method is to be called by a contract with the minter right after being requested\n /// to do so by a `sender` address willing to burn tokens from another `burner` address\n /// @dev The method checks the allowance between the `sender` and the `burner`\n function burnFrom(uint256 amount, address burner, address sender) external;\n\n /// @notice Burns `amount` tokens from a `burner` address\n /// @param amount Amount of tokens to burn\n /// @param burner Address to burn from\n /// @dev This method is to be called by a contract with a minter right on the AgToken after being\n /// requested to do so by an address willing to burn tokens from its address\n function burnSelf(uint256 amount, address burner) external;\n\n // ========================= Treasury Only Functions ===========================\n\n /// @notice Adds a minter in the contract\n /// @param minter Minter address to add\n /// @dev Zero address checks are performed directly in the `Treasury` contract\n function addMinter(address minter) external;\n\n /// @notice Removes a minter from the contract\n /// @param minter Minter address to remove\n /// @dev This function can also be called by a minter wishing to revoke itself\n function removeMinter(address minter) external;\n\n /// @notice Sets a new treasury contract\n /// @param _treasury New treasury address\n function setTreasury(address _treasury) external;\n\n // ========================= External functions ================================\n\n /// @notice Checks whether an address has the right to mint agTokens\n /// @param minter Address for which the minting right should be checked\n /// @return Whether the address has the right to mint agTokens or not\n function isMinter(address minter) external view returns (bool);\n\n /// @notice Get the associated treasury\n function treasury() external view returns (address);\n}\n" + }, + "contracts/interfaces/ICoreBorrow.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.12;\n\n/// @title ICoreBorrow\n/// @author Angle Labs, Inc.\n/// @notice Interface for the `CoreBorrow` contract\n/// @dev This interface only contains functions of the `CoreBorrow` contract which are called by other contracts\n/// of this module\ninterface ICoreBorrow {\n /// @notice Checks if an address corresponds to a treasury of a stablecoin with a flash loan\n /// module initialized on it\n /// @param treasury Address to check\n /// @return Whether the address has the `FLASHLOANER_TREASURY_ROLE` or not\n function isFlashLoanerTreasury(address treasury) external view returns (bool);\n\n /// @notice Checks whether an address is governor of the Angle Protocol or not\n /// @param admin Address to check\n /// @return Whether the address has the `GOVERNOR_ROLE` or not\n function isGovernor(address admin) external view returns (bool);\n\n /// @notice Checks whether an address is governor or a guardian of the Angle Protocol or not\n /// @param admin Address to check\n /// @return Whether the address has the `GUARDIAN_ROLE` or not\n /// @dev Governance should make sure when adding a governor to also give this governor the guardian\n /// role by calling the `addGovernor` function\n function isGovernorOrGuardian(address admin) external view returns (bool);\n}\n" + }, + "contracts/interfaces/IFlashAngle.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.12;\n\nimport \"./IAgToken.sol\";\nimport \"./ICoreBorrow.sol\";\n\n/// @title IFlashAngle\n/// @author Angle Labs, Inc.\n/// @notice Interface for the `FlashAngle` contract\n/// @dev This interface only contains functions of the contract which are called by other contracts\n/// of this module\ninterface IFlashAngle {\n /// @notice Reference to the `CoreBorrow` contract managing the FlashLoan module\n function core() external view returns (ICoreBorrow);\n\n /// @notice Sends the fees taken from flash loans to the treasury contract associated to the stablecoin\n /// @param stablecoin Stablecoin from which profits should be sent\n /// @return balance Amount of profits sent\n /// @dev This function can only be called by the treasury contract\n function accrueInterestToTreasury(IAgToken stablecoin) external returns (uint256 balance);\n\n /// @notice Adds support for a stablecoin\n /// @param _treasury Treasury associated to the stablecoin to add support for\n /// @dev This function can only be called by the `CoreBorrow` contract\n function addStablecoinSupport(address _treasury) external;\n\n /// @notice Removes support for a stablecoin\n /// @param _treasury Treasury associated to the stablecoin to remove support for\n /// @dev This function can only be called by the `CoreBorrow` contract\n function removeStablecoinSupport(address _treasury) external;\n\n /// @notice Sets a new core contract\n /// @param _core Core contract address to set\n /// @dev This function can only be called by the `CoreBorrow` contract\n function setCore(address _core) external;\n}\n" + }, + "contracts/interfaces/IOracle.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.12;\n\nimport \"./ITreasury.sol\";\nimport \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\n\n/// @title IOracle\n/// @author Angle Labs, Inc.\n/// @notice Interface for the `Oracle` contract\n/// @dev This interface only contains functions of the contract which are called by other contracts\n/// of this module\ninterface IOracle {\n /// @notice Reads the rate from the Chainlink circuit and other data provided\n /// @return quoteAmount The current rate between the in-currency and out-currency in the base\n /// of the out currency\n /// @dev For instance if the out currency is EUR (and hence agEUR), then the base of the returned\n /// value is 10**18\n function read() external view returns (uint256);\n\n /// @notice Changes the treasury contract\n /// @param _treasury Address of the new treasury contract\n /// @dev This function can be called by an approved `VaultManager` contract which can call\n /// this function after being requested to do so by a `treasury` contract\n /// @dev In some situations (like reactor contracts), the `VaultManager` may not directly be linked\n /// to the `oracle` contract and as such we may need governors to be able to call this function as well\n function setTreasury(address _treasury) external;\n\n /// @notice Reference to the `treasury` contract handling this `VaultManager`\n function treasury() external view returns (ITreasury treasury);\n\n /// @notice Array with the list of Chainlink feeds in the order in which they are read\n function circuitChainlink() external view returns (AggregatorV3Interface[] memory);\n}\n" + }, + "contracts/interfaces/ITreasury.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.12;\n\nimport \"./IAgToken.sol\";\nimport \"./ICoreBorrow.sol\";\nimport \"./IFlashAngle.sol\";\n\n/// @title ITreasury\n/// @author Angle Labs, Inc.\n/// @notice Interface for the `Treasury` contract\n/// @dev This interface only contains functions of the `Treasury` which are called by other contracts\n/// of this module\ninterface ITreasury {\n /// @notice Stablecoin handled by this `treasury` contract\n function stablecoin() external view returns (IAgToken);\n\n /// @notice Checks whether a given address has the governor role\n /// @param admin Address to check\n /// @return Whether the address has the governor role\n /// @dev Access control is only kept in the `CoreBorrow` contract\n function isGovernor(address admin) external view returns (bool);\n\n /// @notice Checks whether a given address has the guardian or the governor role\n /// @param admin Address to check\n /// @return Whether the address has the guardian or the governor role\n /// @dev Access control is only kept in the `CoreBorrow` contract which means that this function\n /// queries the `CoreBorrow` contract\n function isGovernorOrGuardian(address admin) external view returns (bool);\n\n /// @notice Checks whether a given address has well been initialized in this contract\n /// as a `VaultManager`\n /// @param _vaultManager Address to check\n /// @return Whether the address has been initialized or not\n function isVaultManager(address _vaultManager) external view returns (bool);\n\n /// @notice Sets a new flash loan module for this stablecoin\n /// @param _flashLoanModule Reference to the new flash loan module\n /// @dev This function removes the minting right to the old flash loan module and grants\n /// it to the new module\n function setFlashLoanModule(address _flashLoanModule) external;\n\n /// @notice Gets the vault manager list\n function vaultManagerList(uint256 i) external returns (address);\n}\n" + }, + "contracts/oracle/BaseOracleChainlinkMulti.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\n/*\n * █ \n ***** ▓▓▓ \n * ▓▓▓▓▓▓▓ \n * ///. ▓▓▓▓▓▓▓▓▓▓▓▓▓ \n ***** //////// ▓▓▓▓▓▓▓ \n * ///////////// ▓▓▓ \n ▓▓ ////////////////// █ ▓▓ \n ▓▓ ▓▓ /////////////////////// ▓▓ ▓▓ \n ▓▓ ▓▓ //////////////////////////// ▓▓ ▓▓ \n ▓▓ ▓▓ /////////▓▓▓///////▓▓▓///////// ▓▓ ▓▓ \n ▓▓ ,////////////////////////////////////// ▓▓ ▓▓ \n ▓▓ ////////////////////////////////////////// ▓▓ \n ▓▓ //////////////////////▓▓▓▓///////////////////// \n ,//////////////////////////////////////////////////// \n .////////////////////////////////////////////////////////// \n .//////////////////////////██.,//////////////////////////█ \n .//////////////////////████..,./////////////////////██ \n ...////////////////███████.....,.////////////////███ \n ,.,////////////████████ ........,///////////████ \n .,.,//////█████████ ,.......///////████ \n ,..//████████ ........./████ \n ..,██████ .....,███ \n .██ ,.,█ \n \n \n \n ▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓ ▓▓▓▓▓▓▓▓▓▓ \n ▓▓▓▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓ ▓▓▓▓ \n ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓▓▓▓ \n ▓▓▓ ▓▓ ▓▓▓ ▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ \n*/\n\npragma solidity ^0.8.12;\n\nimport \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\n\nimport \"../interfaces/IOracle.sol\";\nimport \"../interfaces/ITreasury.sol\";\n\n/// @title BaseOracleChainlinkMulti\n/// @author Angle Labs, Inc.\n/// @notice Base Contract to be overriden by all contracts of the protocol\n/// @dev This base contract concerns an oracle that uses Chainlink with multiple pools to read from\n/// @dev All gas-efficient implementation of the `OracleChainlinkMulti` contract should inherit from this\nabstract contract BaseOracleChainlinkMulti is IOracle {\n // ========================= Parameters and References =========================\n\n /// @inheritdoc IOracle\n ITreasury public override treasury;\n /// @notice Represent the maximum amount of time (in seconds) between each Chainlink update\n /// before the price feed is considered stale\n uint32 public stalePeriod;\n\n // =================================== Event ===================================\n\n event StalePeriodUpdated(uint32 _stalePeriod);\n\n // =================================== Errors ===================================\n\n error InvalidChainlinkRate();\n error NotGovernorOrGuardian();\n error NotVaultManagerOrGovernor();\n\n /// @notice Constructor for an oracle using Chainlink with multiple pools to read from\n /// @param _stalePeriod Minimum feed update frequency for the oracle to not revert\n /// @param _treasury Treasury associated to the VaultManager which reads from this feed\n constructor(uint32 _stalePeriod, address _treasury) {\n stalePeriod = _stalePeriod;\n treasury = ITreasury(_treasury);\n }\n\n // ============================= Reading Oracles ===============================\n\n /// @inheritdoc IOracle\n function read() external view virtual override returns (uint256 quoteAmount);\n\n /// @inheritdoc IOracle\n function circuitChainlink() public view virtual returns (AggregatorV3Interface[] memory);\n\n /// @notice Reads a Chainlink feed using a quote amount and converts the quote amount to\n /// the out-currency\n /// @param quoteAmount The amount for which to compute the price expressed with base decimal\n /// @param feed Chainlink feed to query\n /// @param multiplied Whether the ratio outputted by Chainlink should be multiplied or divided\n /// to the `quoteAmount`\n /// @param decimals Number of decimals of the corresponding Chainlink pair\n /// @return The `quoteAmount` converted in out-currency\n function _readChainlinkFeed(\n uint256 quoteAmount,\n AggregatorV3Interface feed,\n uint8 multiplied,\n uint256 decimals\n ) internal view returns (uint256) {\n (uint80 roundId, int256 ratio, , uint256 updatedAt, uint80 answeredInRound) = feed.latestRoundData();\n if (ratio <= 0 || roundId > answeredInRound || block.timestamp - updatedAt > stalePeriod)\n revert InvalidChainlinkRate();\n uint256 castedRatio = uint256(ratio);\n // Checking whether we should multiply or divide by the ratio computed\n if (multiplied == 1) return (quoteAmount * castedRatio) / (10 ** decimals);\n else return (quoteAmount * (10 ** decimals)) / castedRatio;\n }\n\n // ======================= Governance Related Functions ========================\n\n /// @notice Changes the stale period\n /// @param _stalePeriod New stale period (in seconds)\n function changeStalePeriod(uint32 _stalePeriod) external {\n if (!treasury.isGovernorOrGuardian(msg.sender)) revert NotGovernorOrGuardian();\n stalePeriod = _stalePeriod;\n emit StalePeriodUpdated(_stalePeriod);\n }\n\n /// @inheritdoc IOracle\n function setTreasury(address _treasury) external override {\n if (!treasury.isVaultManager(msg.sender) && !treasury.isGovernor(msg.sender))\n revert NotVaultManagerOrGovernor();\n treasury = ITreasury(_treasury);\n }\n}\n" + }, + "contracts/oracle/BaseOracleChainlinkMultiTwoFeeds.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.12;\n\nimport \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\n\nimport \"./BaseOracleChainlinkMulti.sol\";\n\n/// @title BaseOracleChainlinkMultiTwoFeeds\n/// @author Angle Labs, Inc.\n/// @notice Base contract for an oracle that reads into two Chainlink feeds (including an EUR/USD feed) which both have\n/// 8 decimals\nabstract contract BaseOracleChainlinkMultiTwoFeeds is BaseOracleChainlinkMulti {\n constructor(uint32 _stalePeriod, address _treasury) BaseOracleChainlinkMulti(_stalePeriod, _treasury) {}\n\n /// @notice Returns the quote amount of the oracle contract\n function _getQuoteAmount() internal view virtual returns (uint256) {\n return 10 ** 18;\n }\n\n /// @inheritdoc IOracle\n function read() public view virtual override returns (uint256 quoteAmount) {\n quoteAmount = _getQuoteAmount();\n AggregatorV3Interface[] memory _circuitChainlink = circuitChainlink();\n uint8[2] memory circuitChainIsMultiplied = [1, 0];\n uint8[2] memory chainlinkDecimals = [8, 8];\n uint256 circuitLength = _circuitChainlink.length;\n for (uint256 i; i < circuitLength; ++i) {\n quoteAmount = _readChainlinkFeed(\n quoteAmount,\n _circuitChainlink[i],\n circuitChainIsMultiplied[i],\n chainlinkDecimals[i]\n );\n }\n }\n}\n" + }, + "contracts/oracle/implementations/arbitrum/EUR/OracleSTEURETHChainlinkArbitrum.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.12;\n\nimport \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\n\nimport \"../../../BaseOracleChainlinkMultiTwoFeeds.sol\";\nimport \"../../../../interfaces/external/IERC4626.sol\";\n\n/// @title OracleSTEURETHChainlinkArbitrum\n/// @author Angle Labs, Inc.\n/// @notice Gives the price of stEUR in ETH in base 18\ncontract OracleSTEURETHChainlinkArbitrum is BaseOracleChainlinkMultiTwoFeeds, AggregatorV3Interface {\n string public constant DESCRIPTION = \"stEUR/ETH Oracle\";\n IERC4626 public constant STEUR = IERC4626(0x004626A008B1aCdC4c74ab51644093b155e59A23);\n\n constructor(uint32 _stalePeriod, address _treasury) BaseOracleChainlinkMultiTwoFeeds(_stalePeriod, _treasury) {}\n\n /// @inheritdoc IOracle\n function circuitChainlink() public pure override returns (AggregatorV3Interface[] memory) {\n AggregatorV3Interface[] memory _circuitChainlink = new AggregatorV3Interface[](2);\n // Oracle agEUR/USD - Redstone\n _circuitChainlink[0] = AggregatorV3Interface(0x37963F10245e7c3a10c0E9d43a6E617B4Bc8440A);\n // Oracle ETH/USD - Chainlink\n _circuitChainlink[1] = AggregatorV3Interface(0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612);\n return _circuitChainlink;\n }\n\n /// @inheritdoc BaseOracleChainlinkMultiTwoFeeds\n function _getQuoteAmount() internal view override returns (uint256) {\n return STEUR.convertToAssets(1 ether);\n }\n\n /*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n CHAINLINK INTERFACE COMPATIBILITY \n //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/\n\n /// @inheritdoc AggregatorV3Interface\n function decimals() external pure returns (uint8) {\n return 18;\n }\n\n /// @inheritdoc AggregatorV3Interface\n function description() external pure returns (string memory desc) {\n desc = \"Angle stEUR/ETH Price Feed\";\n }\n\n /// @inheritdoc AggregatorV3Interface\n function version() external pure returns (uint256) {\n return 1;\n }\n\n /// @inheritdoc AggregatorV3Interface\n /// @return roundID\n /// @return aggregatorPrice\n /// @return startedAt\n /// @return timestamp\n /// @return answeredInRound\n /// @dev The `roundId`, `startedAt` and `answeredInRound` values return in this function must be disregarded\n /// @dev In order not to multiply oracle calls, the timestamp returned here is the `block.timestamp`.\n /// The contract still performs an heartbeat check for every oracle value that it reads, and the accurate\n /// value of the `timestamp` (if this one is taken as the minimum between the last update timestamp\n /// of the two oracles) is between: current timestamp and the current timestamp minus `stalePeriod`\n function latestRoundData() public view returns (uint80, int256, uint256, uint256, uint80) {\n return (0, int256(read()), 0, block.timestamp, 0);\n }\n\n /// @inheritdoc AggregatorV3Interface\n /// @dev This function always returns the latestRoundData\n function getRoundData(uint80) external view returns (uint80, int256, uint256, uint256, uint80) {\n return latestRoundData();\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "devdoc", + "userdoc" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/package.json b/package.json index beef0d96..e11552d3 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "check-upgradeability": "hardhat run scripts/upgradeability.ts", "coverage": "hardhat coverage", "coverage:foundry": "forge coverage --report lcov", - "deploy": "hardhat deploy --tags lzSetupNewStable --network ", + "deploy": "hardhat deploy --tags newOracle --network ", "etherscan": "hardhat etherscan-verify --network", "foundry:deploy": "forge script --broadcast --verify -vvvv --rpc-url", "generate-types-from-abis": "typechain --target ethers-v5 --out-dir typechain './export/abi/*.json'",