Skip to content

Commit

Permalink
Merge pull request #206 from VenusProtocol/develop
Browse files Browse the repository at this point in the history
New release
  • Loading branch information
chechu authored Jul 18, 2024
2 parents e67ed62 + 7783ddd commit c63e2b8
Show file tree
Hide file tree
Showing 39 changed files with 11,481 additions and 305 deletions.
45 changes: 45 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,48 @@
## [2.4.0-dev.2](https://github.com/VenusProtocol/oracle/compare/v2.4.0-dev.1...v2.4.0-dev.2) (2024-06-20)


### Features

* updating deployment files ([28900dd](https://github.com/VenusProtocol/oracle/commit/28900dd3c7a6d8fd6bc4f8ee310b649430ea715f))
* updating deployment files ([41bac60](https://github.com/VenusProtocol/oracle/commit/41bac602d0b57b3c325c762e391b8132b57d5891))
* use ratio for price difference ([f76cf1e](https://github.com/VenusProtocol/oracle/commit/f76cf1e0e5e29051ad7e9aace4a576321edeb8e6))


### Bug Fixes

* added acm ([2a10937](https://github.com/VenusProtocol/oracle/commit/2a109374d3c40aef882bfc8b067548dd9b9aa937))
* added netspec ([54462b8](https://github.com/VenusProtocol/oracle/commit/54462b89a393d478f90d1154134d6c75d27753f5))
* added price difference check ([526eacf](https://github.com/VenusProtocol/oracle/commit/526eacfaa0f193e13e1e5fa66c1b638106f4753e))
* changed order ([a46c67d](https://github.com/VenusProtocol/oracle/commit/a46c67d8b95648dc7ba3bb38fb808cb1dd4dc6dc))
* deployed on ethereum ([25ab625](https://github.com/VenusProtocol/oracle/commit/25ab625a97df1dd5f4edbf71687e1523851ed0a2))
* deployed oracle ([c5ae0fa](https://github.com/VenusProtocol/oracle/commit/c5ae0fae3dca410c5abbc2546b15c2df4398f060))
* fix comment ([fc62a15](https://github.com/VenusProtocol/oracle/commit/fc62a15d090b7d8e7577a5dbcf07a6a39cbb57f0))
* fix comment ([3058ef1](https://github.com/VenusProtocol/oracle/commit/3058ef1a794a73a43c43a792af0309fc33ccf852))
* fixed tests ([0206218](https://github.com/VenusProtocol/oracle/commit/02062182753393f1d982448e043f601226122aef))
* fixed vars ([5512927](https://github.com/VenusProtocol/oracle/commit/5512927a65f7b2fb8fe422de69374780d90da0ea))
* make sfrxETH immutable ([95e0494](https://github.com/VenusProtocol/oracle/commit/95e049416e75cda023c323d7faaa3fddee115682))
* redeployed oracle on testnet ([5b3b6ed](https://github.com/VenusProtocol/oracle/commit/5b3b6ed0955121ad0b6fb5aa7422929811d2b748))
* remove correlated token oracle ([f475e6b](https://github.com/VenusProtocol/oracle/commit/f475e6b5c3de15ecf705b9b7a9fef805acc32622))
* removed ISfrxETH ([6f47ec2](https://github.com/VenusProtocol/oracle/commit/6f47ec2c70152c580bf13023c96e2b34a8f12e52))
* revert config ([3991356](https://github.com/VenusProtocol/oracle/commit/3991356f9ad8e293cb67d91fa9b5fdbbdfb8513e))
* sfe-03 ([b24ef72](https://github.com/VenusProtocol/oracle/commit/b24ef729a7f1b13d1c2b572e4717612275659dd1))
* sfe-05 ([6130942](https://github.com/VenusProtocol/oracle/commit/6130942986f3e75725ea295b1e634c73df1601da))
* update var name ([ae84726](https://github.com/VenusProtocol/oracle/commit/ae84726383d1e858b811453ddc40ab94b6c30593))
* use sfrxEthFraxOracle oracle ([fc52a39](https://github.com/VenusProtocol/oracle/commit/fc52a39b0033916df264551d5364ed43f1ca79da))
* ven-1 ([0cd68b2](https://github.com/VenusProtocol/oracle/commit/0cd68b2148a20733c3d74fa8f74016ee9156c9e2))
* ven-2 ([6374a84](https://github.com/VenusProtocol/oracle/commit/6374a844a89c874887da7349a094b5f982daba95))

## [2.4.0-dev.1](https://github.com/VenusProtocol/oracle/compare/v2.3.0...v2.4.0-dev.1) (2024-06-18)


### Features

* add rsETH oracle deployments on ethereum ([968d849](https://github.com/VenusProtocol/oracle/commit/968d849bf414aebbf9615c98075b6aa7374fdf63))
* deploy one jump oracle on sepolia ([7079a6c](https://github.com/VenusProtocol/oracle/commit/7079a6c5b8e52c13278240755e23cdb7a8b74eb7))
* updating deployment files ([bccaec6](https://github.com/VenusProtocol/oracle/commit/bccaec67c7bc5ff330d4cfcfadf94db2fe584932))
* updating deployment files ([f426c17](https://github.com/VenusProtocol/oracle/commit/f426c17920ce1291e15ea77781e6404721f2b846))
* updating deployment files ([62fa36d](https://github.com/VenusProtocol/oracle/commit/62fa36da6c0ce3eee7db8377f86ed01235a09c14))

## [2.3.0](https://github.com/VenusProtocol/oracle/compare/v2.2.0...v2.3.0) (2024-05-31)


Expand Down
Binary file added audits/110_sfrxETHOracle_certik_20240517.pdf
Binary file not shown.
Binary file added audits/111_sfrxETHOracle_quantstamp_20240530.pdf
Binary file not shown.
7 changes: 0 additions & 7 deletions contracts/interfaces/ISfrxETH.sol

This file was deleted.

6 changes: 6 additions & 0 deletions contracts/interfaces/ISfrxEthFraxOracle.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.25;

interface ISfrxEthFraxOracle {
function getPrices() external view returns (bool _isbadData, uint256 _priceLow, uint256 _priceHigh);
}
103 changes: 91 additions & 12 deletions contracts/oracles/SFrxETHOracle.sol
Original file line number Diff line number Diff line change
@@ -1,29 +1,108 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.25;

import { ISfrxETH } from "../interfaces/ISfrxETH.sol";
import { CorrelatedTokenOracle } from "./common/CorrelatedTokenOracle.sol";
import { ISfrxEthFraxOracle } from "../interfaces/ISfrxEthFraxOracle.sol";
import { ensureNonzeroAddress, ensureNonzeroValue } from "@venusprotocol/solidity-utilities/contracts/validators.sol";
import { EXP_SCALE } from "@venusprotocol/solidity-utilities/contracts/constants.sol";
import { AccessControlledV8 } from "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol";
import { OracleInterface } from "../interfaces/OracleInterface.sol";

/**
* @title SFrxETHOracle
* @author Venus
* @notice This oracle fetches the price of sfrxETH
*/
contract SFrxETHOracle is CorrelatedTokenOracle {
contract SFrxETHOracle is AccessControlledV8, OracleInterface {
/// @notice Address of SfrxEthFraxOracle
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
ISfrxEthFraxOracle public immutable SFRXETH_FRAX_ORACLE;

/// @notice Address of sfrxETH
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address public immutable SFRXETH;

/// @notice Maximum allowed price difference
uint256 public maxAllowedPriceDifference;

/// @notice Emits when the maximum allowed price difference is updated
event MaxAllowedPriceDifferenceUpdated(uint256 oldMaxAllowedPriceDifference, uint256 newMaxAllowedPriceDifference);

/// @notice Thrown if the price data is invalid
error BadPriceData();

/// @notice Thrown if the price difference exceeds the allowed limit
error PriceDifferenceExceeded();

/// @notice Thrown if the token address is invalid
error InvalidTokenAddress();

/// @notice Constructor for the implementation contract.
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(
address sfrxETH,
address frxETH,
address resilientOracle
) CorrelatedTokenOracle(sfrxETH, frxETH, resilientOracle) {}
/// @custom:error ZeroAddressNotAllowed is thrown when `_sfrxEthFraxOracle` or `_sfrxETH` are the zero address
constructor(address _sfrxEthFraxOracle, address _sfrxETH) {
ensureNonzeroAddress(_sfrxEthFraxOracle);
ensureNonzeroAddress(_sfrxETH);

SFRXETH_FRAX_ORACLE = ISfrxEthFraxOracle(_sfrxEthFraxOracle);
SFRXETH = _sfrxETH;

_disableInitializers();
}

/**
* @notice Sets the contracts required to fetch prices
* @param _accessControlManager Address of the access control manager contract
* @param _maxAllowedPriceDifference Maximum allowed price difference
* @custom:error ZeroValueNotAllowed is thrown if `_maxAllowedPriceDifference` is zero
*/
function initialize(address _accessControlManager, uint256 _maxAllowedPriceDifference) external initializer {
ensureNonzeroValue(_maxAllowedPriceDifference);

__AccessControlled_init(_accessControlManager);
maxAllowedPriceDifference = _maxAllowedPriceDifference;
}

/**
* @notice Sets the maximum allowed price difference
* @param _maxAllowedPriceDifference Maximum allowed price difference
* @custom:error ZeroValueNotAllowed is thrown if `_maxAllowedPriceDifference` is zero
*/
function setMaxAllowedPriceDifference(uint256 _maxAllowedPriceDifference) external {
_checkAccessAllowed("setMaxAllowedPriceDifference(uint256)");
ensureNonzeroValue(_maxAllowedPriceDifference);

emit MaxAllowedPriceDifferenceUpdated(maxAllowedPriceDifference, _maxAllowedPriceDifference);
maxAllowedPriceDifference = _maxAllowedPriceDifference;
}

/**
* @notice Gets the frxETH for 1 sfrxETH
* @return amount Amount of frxETH
* @notice Fetches the USD price of sfrxETH
* @param asset Address of the sfrxETH token
* @return price The price scaled by 1e18
* @custom:error InvalidTokenAddress is thrown when the `asset` is not the sfrxETH token (`SFRXETH`)
* @custom:error BadPriceData is thrown if the `SFRXETH_FRAX_ORACLE` oracle informs it has bad data
* @custom:error ZeroValueNotAllowed is thrown if the prices (low or high, in USD) are zero
* @custom:error PriceDifferenceExceeded is thrown if priceHigh/priceLow is greater than `maxAllowedPriceDifference`
*/
function _getUnderlyingAmount() internal view override returns (uint256) {
return ISfrxETH(CORRELATED_TOKEN).convertToAssets(EXP_SCALE);
function getPrice(address asset) external view returns (uint256) {
if (asset != SFRXETH) revert InvalidTokenAddress();

(bool isBadData, uint256 priceLow, uint256 priceHigh) = SFRXETH_FRAX_ORACLE.getPrices();

if (isBadData) revert BadPriceData();

// calculate price in USD
uint256 priceHighInUSD = (EXP_SCALE ** 2) / priceLow;
uint256 priceLowInUSD = (EXP_SCALE ** 2) / priceHigh;

ensureNonzeroValue(priceHighInUSD);
ensureNonzeroValue(priceLowInUSD);

// validate price difference
uint256 difference = (priceHighInUSD * EXP_SCALE) / priceLowInUSD;
if (difference > maxAllowedPriceDifference) revert PriceDifferenceExceeded();

// calculate and return average price
return (priceHighInUSD + priceLowInUSD) / 2;
}
}
23 changes: 23 additions & 0 deletions contracts/oracles/mocks/MockSFrxEthFraxOracle.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.25;

import "../../interfaces/ISfrxEthFraxOracle.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract MockSfrxEthFraxOracle is ISfrxEthFraxOracle, Ownable {
bool public isBadData;
uint256 public priceLow;
uint256 public priceHigh;

constructor() Ownable() {}

function setPrices(bool _isBadData, uint256 _priceLow, uint256 _priceHigh) external onlyOwner {
isBadData = _isBadData;
priceLow = _priceLow;
priceHigh = _priceHigh;
}

function getPrices() external view override returns (bool, uint256, uint256) {
return (isBadData, priceLow, priceHigh);
}
}
56 changes: 56 additions & 0 deletions deploy/8-deploy-rsETH-oracles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import hre from "hardhat";
import { DeployFunction } from "hardhat-deploy/dist/types";
import { HardhatRuntimeEnvironment } from "hardhat/types";

import { ADDRESSES } from "../helpers/deploymentConfig";

const func: DeployFunction = async function ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) {
const { deploy } = deployments;
const { deployer } = await getNamedAccounts();
const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer;
let WETH;
let rsETH;
if (network.name === "sepolia" || network.name === "ethereum") {
({ WETH } = ADDRESSES[network.name]);
rsETH =
network.name === "sepolia"
? "0xfA0614E5C803E15070d31f7C38d2d430EBe68E47"
: "0xA1290d69c65A6Fe4DF752f95823fae25cB99e5A7";
}

console.log(`Timelock (${proxyOwnerAddress})`);
const redStoneOracle = await hre.ethers.getContract("RedStoneOracle");
const resilientOracle = await hre.ethers.getContract("ResilientOracle");
const chainlinkOracle = await hre.ethers.getContract("ChainlinkOracle");

await deploy("rsETHOneJumpRedStoneOracle", {
contract: "OneJumpOracle",
from: deployer,
log: true,
deterministicDeployment: false,
args: [rsETH, WETH, resilientOracle.address, redStoneOracle.address],
proxy: {
owner: proxyOwnerAddress,
proxyContract: "OptimizedTransparentProxy",
},
skipIfAlreadyDeployed: true,
});

await deploy("rsETHOneJumpChainlinkOracle", {
contract: "OneJumpOracle",
from: deployer,
log: true,
deterministicDeployment: false,
args: [rsETH, WETH, resilientOracle.address, chainlinkOracle.address],
proxy: {
owner: proxyOwnerAddress,
proxyContract: "OptimizedTransparentProxy",
},
skipIfAlreadyDeployed: true,
});
};

func.skip = async () => hre.network.name !== "ethereum" && hre.network.name !== "sepolia";

func.tags = ["rsETHOneJumpOracles"];
export default func;
62 changes: 62 additions & 0 deletions deploy/8-deploy-sfrxeth-oracle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { parseUnits } from "ethers/lib/utils";
import { ethers } from "hardhat";
import { DeployFunction } from "hardhat-deploy/dist/types";
import { HardhatRuntimeEnvironment } from "hardhat/types";

import { ADDRESSES } from "../helpers/deploymentConfig";

const func: DeployFunction = async ({ getNamedAccounts, deployments, network }: HardhatRuntimeEnvironment) => {
const { deploy } = deployments;
const { deployer } = await getNamedAccounts();

const proxyOwnerAddress = network.live ? ADDRESSES[network.name].timelock : deployer;

const { sfrxETH, SfrxEthFraxOracle, acm } = ADDRESSES[network.name];
const maxAllowedPriceDifference = parseUnits("1.14", 18);

let SfrxEthFraxOracleAddress = SfrxEthFraxOracle;
if (!SfrxEthFraxOracle) {
await deploy("MockSfrxEthFraxOracle", {
contract: "MockSfrxEthFraxOracle",
from: deployer,
log: true,
autoMine: true,
skipIfAlreadyDeployed: true,
args: [],
});

const mockSfrxEthFraxOracle = await ethers.getContract("MockSfrxEthFraxOracle");
SfrxEthFraxOracleAddress = mockSfrxEthFraxOracle.address;

if ((await mockSfrxEthFraxOracle.owner()) === deployer) {
await mockSfrxEthFraxOracle.transferOwnership(proxyOwnerAddress);
}
}

await deploy("SFrxETHOracle", {
contract: "SFrxETHOracle",
from: deployer,
log: true,
deterministicDeployment: false,
args: [SfrxEthFraxOracleAddress, sfrxETH],
proxy: {
owner: proxyOwnerAddress,
proxyContract: "OptimizedTransparentProxy",
execute: {
methodName: "initialize",
args: [acm, maxAllowedPriceDifference],
},
},
skipIfAlreadyDeployed: true,
});

const sfrxETHOracle = await ethers.getContract("SFrxETHOracle");

if ((await sfrxETHOracle.owner()) === deployer) {
await sfrxETHOracle.transferOwnership(proxyOwnerAddress);
}
};

export default func;
func.tags = ["sFraxETHOracle"];
func.skip = async (hre: HardhatRuntimeEnvironment) => hre.network.name !== "ethereum" && hre.network.name !== "sepolia";
Loading

0 comments on commit c63e2b8

Please sign in to comment.