Skip to content
This repository has been archived by the owner on Oct 26, 2022. It is now read-only.

Created OpenOracleFrameworkOracle.sol #28

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions contracts/oracles/OpenOracleFrameworkOracle.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// SPDX-License-Identifier: MIT
// Using the same Copyleft License as in the original Repository
pragma solidity 0.6.12;
import "@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol";
import "../interfaces/IOracle.sol";

// Open Oracle Framework Interface
interface IOpenOracleFramework {
function getFeed(uint256 feedID) external view returns (uint256, uint256, uint256);
}

// Open Oracle Framework TWAP Interface
interface IOpenOracleFrameworkTWAP {
function getTWAP(
address OOFContract,
uint256[] memory feedIDs,
uint256[] memory timestampstart,
uint256[] memory timestampfinish,
bool strictMode)
external view returns (uint256[] memory TWAP);
}

contract OpenOracleFramework is IOracle {
using BoringMath for uint256; // Keep everything in uint256

// Calculates the latest rate
function _get(
address oracle,
uint256 feedId
) internal view returns (uint256) {
uint256 price;
uint256 decimals;
(price, , decimals) = IOpenOracleFramework(oracle).getFeed(feedId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the spot price manipulatable?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As these are oracles they choose the spot price source, they would probably use a platform like coingecko or the ETH price index which already uses multiple exchange prices to form prices making manipulation almost impossible unless spending bns USD. We also have the oracles have a threshold for multisjg, so 1 price submit will not be returned by the oracle as the latest, only median prices from n threshold.

return price / decimals;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this already conform to the Kashi oracle standard of providing the price of 1e18 of asset?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We standardize all feed returns to be 18 dec yes.

}

// Calculates the 24h TWAP rate
function _getTWAP(
address twap,
address oracle,
uint256 feedId
) internal view returns (uint256) {

uint256 decimals;
(,,decimals) = IOpenOracleFramework(oracle).getFeed(feedId);

uint256[] memory feedIdInput = new uint256[](1);
uint256[] memory twapStart = new uint256[](1);
uint256[] memory twapEnd = new uint256[](1);

feedIdInput[0] = feedId;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have any mapping from feedIds to price feeds? (what the price feed represents e.g. ETH/USDC
Did you make any thoughts about combining price feeds?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no mappings as oracles are free to submit any data they want for their oracle. You could simply check through getfeedlist for a matching name though.

twapStart[0] = block.timestamp - 60*60*24;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What reasoning makes you choose a 24hour TWAP?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 24h TWAP gives enough data and time to help protect flash events, while also being flexible enough to adapt to sudden market changes. The 24h TWAP provided could easily be changed though, depending on how much actual compatibility, the front end could pool creators choose the TWAP when an oof oracles detected, as all oracles are compatible with arb TWAPs.

twapEnd[0] = block.timestamp;

uint256 price = IOpenOracleFrameworkTWAP(twap).getTWAP(oracle,feedIdInput,twapStart,twapEnd,false)[0];
return price / decimals;
}

function getDataParameter(
address multiply,
address divide,
uint256 decimals
) public pure returns (bytes memory) {
return abi.encode(multiply, divide, decimals);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the encoding here is incoherent with get and peek

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the documentation, we assumed that these fns act as getspot and getprice, and assumed there was a need to know spot when TWAPs were used. So get was made to get the latest price update where peek waa the TWAP value to be protected.

}

// Get the latest exchange rate
/// @inheritdoc IOracle
function get(bytes calldata data) public override returns (bool, uint256) {
(address oracle, uint256 feedId) = abi.decode(data, (address, uint256));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the data encoded seems to be different between peek and get

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See before

return (true, _get(oracle, feedId));
}

// Check the last exchange rate without any state changes
/// @inheritdoc IOracle
function peek(bytes calldata data) public view override returns (bool, uint256) {
(address twap, address oracle, uint256 feedId) = abi.decode(data, (address, address, uint256));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should Oracle and TWAP be hardcoded to the official deployments?
0x00f0feed50DcDF57b4f1B532E8f5e7f291E0C84b and 0x76D98B6d5165F68cfD948702Bf92C3a53b5f57A1 respectfully?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oracle should not as that oracles simply a reference oracle ran by us, the real power from oof and use would be for anyone to use the framework to create pools for lending. The TWAP can be hardcoded though as thats oracle agnostic and just a tool to grab all values and create the TWAP.

return (true, _getTWAP(twap, oracle, feedId));
}

// Check the current spot exchange rate without any state changes
/// @inheritdoc IOracle
function peekSpot(bytes calldata data) external view override returns (uint256 rate) {
(address oracle, uint256 feedId) = abi.decode(data, (address, uint256));
return _get(oracle, feedId);
}

/// @inheritdoc IOracle
function name(bytes calldata) public view override returns (string memory) {
return "Open Oracle Framework";
}

/// @inheritdoc IOracle
function symbol(bytes calldata) public view override returns (string memory) {
return "OOF";
}
}