Skip to content

Commit

Permalink
fix: use abstract contract for wstETH oracle
Browse files Browse the repository at this point in the history
  • Loading branch information
web3rover committed Feb 29, 2024
1 parent 6ba9144 commit 571a6a1
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 56 deletions.
65 changes: 16 additions & 49 deletions contracts/oracles/WstETHOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,71 +5,38 @@ import { OracleInterface } from "../interfaces/OracleInterface.sol";
import { IStETH } from "../interfaces/IStETH.sol";
import { ensureNonzeroAddress } from "@venusprotocol/solidity-utilities/contracts/validators.sol";
import { EXP_SCALE } from "@venusprotocol/solidity-utilities/contracts/constants.sol";
import { WrappedLiquidStakedTokenOracle } from "./common/WrappedLiquidStakedTokenOracle.sol";

/**
* @title WstETHOracle
* @author Venus
* @notice Depending on the equivalence flag price is either based on assumption that 1 stETH = 1 ETH
* or the price of stETH/USD (secondary market price) is obtained from the oracle.
*/
contract WstETHOracle is OracleInterface {
/// @notice A flag assuming 1:1 price equivalence between stETH/ETH
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
bool public immutable ASSUME_STETH_ETH_EQUIVALENCE;

/// @notice Address of stETH
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
IStETH public immutable STETH;

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

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

/// @notice Address of Resilient Oracle
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
OracleInterface public immutable RESILIENT_ORACLE;

contract WstETHOracle is WrappedLiquidStakedTokenOracle {
/// @notice Constructor for the implementation contract.
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(
address wstETHAddress,
address wETHAddress,
address stETHAddress,
address wstETHAddress,
address resilientOracleAddress,
bool assumeEquivalence
) {
ensureNonzeroAddress(wstETHAddress);
ensureNonzeroAddress(wETHAddress);
ensureNonzeroAddress(stETHAddress);
ensureNonzeroAddress(resilientOracleAddress);
WSTETH_ADDRESS = wstETHAddress;
WETH_ADDRESS = wETHAddress;
STETH = IStETH(stETHAddress);
RESILIENT_ORACLE = OracleInterface(resilientOracleAddress);
ASSUME_STETH_ETH_EQUIVALENCE = assumeEquivalence;
}
)
WrappedLiquidStakedTokenOracle(
wETHAddress,
stETHAddress,
wstETHAddress,
resilientOracleAddress,
assumeEquivalence
)
{}

/**
* @notice Gets the USD price of wstETH asset
* @dev Depending on the equivalence flag price is either based on assumption that 1 stETH = 1 ETH
* or the price of stETH/USD (secondary market price) is obtained from the oracle
* @param asset Address of wstETH
* @return wstETH Price in USD scaled by 1e18
* @notice Gets the stETH for 1 wstETH
* @return amount Amount of stETH
*/
function getPrice(address asset) public view returns (uint256) {
if (asset != WSTETH_ADDRESS) revert("wrong wstETH address");

// get stETH amount for 1 wstETH scaled by 1e18
uint256 stETHAmount = STETH.getPooledEthByShares(1 ether);

// price is scaled 1e18 (oracle returns 36 - asset decimal scale)
uint256 stETHUSDPrice = RESILIENT_ORACLE.getPrice(ASSUME_STETH_ETH_EQUIVALENCE ? WETH_ADDRESS : address(STETH));

// stETHAmount (for 1 wstETH) * stETHUSDPrice / 1e18
return (stETHAmount * stETHUSDPrice) / EXP_SCALE;
function getRebaseTokenAmount() internal view override returns (uint256) {
return IStETH(REBASE_TOKEN).getPooledEthByShares(1 ether);
}
}
14 changes: 7 additions & 7 deletions test/WstETHOracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,31 +39,31 @@ describe("WstETHOracle unit tests", () => {

describe("deployment", () => {
it("revert if wstETH address is 0", async () => {
await expect(WsETHOracleFactory.deploy(addr0000, WETH, stETHMock.address, resilientOracleMock.address, true)).to
await expect(WsETHOracleFactory.deploy(WETH, stETHMock.address, addr0000, resilientOracleMock.address, true)).to
.be.reverted;
});
it("revert if WETH address is 0", async () => {
await expect(WsETHOracleFactory.deploy(WSTETH, addr0000, stETHMock.address, resilientOracleMock.address, true)).to
await expect(WsETHOracleFactory.deploy(addr0000, stETHMock.address, WSTETH, resilientOracleMock.address, true)).to
.be.reverted;
});
it("revert if stETH address is 0", async () => {
await expect(WsETHOracleFactory.deploy(WSTETH, WETH, addr0000, resilientOracleMock.address, true)).to.be.reverted;
await expect(WsETHOracleFactory.deploy(WETH, addr0000, WSTETH, resilientOracleMock.address, true)).to.be.reverted;
});
it("revert if ResilientOracle address is 0", async () => {
await expect(WsETHOracleFactory.deploy(WSTETH, WETH, stETHMock.address, addr0000, true)).to.be.reverted;
await expect(WsETHOracleFactory.deploy(WETH, stETHMock.address, WSTETH, addr0000, true)).to.be.reverted;
});
it("should deploy contract", async () => {
wstETHOracleEquivalentRatio = await WsETHOracleFactory.deploy(
WSTETH,
WETH,
stETHMock.address,
WSTETH,
resilientOracleMock.address,
true,
);
wstETHOracleNonEquivalentRatio = await WsETHOracleFactory.deploy(
WSTETH,
WETH,
stETHMock.address,
WSTETH,
resilientOracleMock.address,
false,
);
Expand All @@ -72,7 +72,7 @@ describe("WstETHOracle unit tests", () => {

describe("getPrice", () => {
it("revert if wstETH address is wrong", async () => {
await expect(wstETHOracleEquivalentRatio.getPrice(addr0000)).to.be.revertedWith("wrong wstETH address");
await expect(wstETHOracleEquivalentRatio.getPrice(addr0000)).to.be.revertedWith("wrong token address");
});

it("should get correct price assuming 1/1 ratio", async () => {
Expand Down

0 comments on commit 571a6a1

Please sign in to comment.