preface
2020 ~ 2021 is a Defi era. Many public chains begin to support EVM and start Web3 0 Including Algorand, BCH, BSC, NEO and Conflux, etc. Many public chain ecological applications appear explosively, such as Gamefi and a variety of Defi protocols. However, Oracle service is a very important service in various ecosystems of Defi. Many Defi protocols require a Oracle contract for quotation. In order to solve the problem that there is no Oracle in the new public chain ecology, I open source a centralized blockchain Oracle I wrote in TriangleDAO. The core team or core community personnel can be deployed to the corresponding chain to make a temporary centralized blockchain Oracle scheme. This is also suitable for the alliance chain. The alliance chain should have little or no Oracle service.
Open source address:
https://github.com/shanxuanch...
Technical architecture (v1.0)
The core is actually two contracts: one is triangle oracle Sol, another pricefeed sol.
TriangleOracle.sol inherits the IERC2362 standard and mainly has two functions: putpierce and ValueFor. There is a regular process that reads the price from Binance and Okex every 5 minutes, and then triggers putPrice to write the price to the chain.
pragma solidity 0.6.11; import "./Ownable.sol"; import "./Interfaces/IERC2362.sol"; contract TriangleOracle is Ownable, IERC2362 { // 32 + 16 + 16 = 64 bytes // default 1e+18 struct PriceOracle { int256 price; // 16 bytes uint256 timestamp; uint256 status; // 16 bytes } PriceOracle latestPrice; event PutLatestTokenPrice(int256 price, uint256 timestamp, uint256 status); function putPrice(bytes32 _id, int256 price, uint256 timestamp) public onlyOwner { uint256 _status = 200; latestPrice = PriceOracle ({ price: price, timestamp: timestamp, status: _status }); emit PutLatestTokenPrice(price,timestamp, _status); } function valueFor(bytes32 _id) external view override returns(int256,uint256,uint256) { return (latestPrice.price, latestPrice.timestamp, latestPrice.status); } }
The responsibility of the PriceFeed contract is to read triangle oracle Sol, and then save the price to the variable lastGoodPrice so that other contracts can read the price. There are other logic, such as scale. More importantly, it involves the logic of updatability and contract interaction, which improves my understanding of smart contract by an order of magnitude.
// SPDX-License-Identifier: MIT pragma solidity 0.6.11; import "./Dependencies/SafeMath.sol"; import "./Interfaces/IERC2362.sol"; import "./Interfaces/IPriceFeed.sol"; import "./Dependencies/Initializable.sol"; import "./Dependencies/CheckContract.sol"; contract PriceFeed is CheckContract, IPriceFeed, Initializable { using SafeMath for uint256; uint constant public TARGET_DIGITS = 18; // CFX/USDT assertID bytes32 constant public assetID = bytes32(0x65784185a07d3add5e7a99a6ddd4477e3c8caad717bac3ba3c3361d99a978c29); struct WitnetResponse { int256 value; uint256 _timestamp; uint256 status; } IERC2362 public witnet; uint public lastGoodPrice; event LastGoodPriceUpdated(uint _lastGoodPrice); // --- Dependency setters --- function initialize(address _IWitnetCFXUSDTAddress) public initializer { checkContract(_IWitnetCFXUSDTAddress); witnet = IERC2362(_IWitnetCFXUSDTAddress); WitnetResponse memory witnetResponse = _getCurrentWitnetResponse(assetID); _storePrice(witnetResponse); } function getPrice() external view returns (uint) { return lastGoodPrice; } function fetchPrice() external override returns (uint) { WitnetResponse memory witnetResponse = _getCurrentWitnetResponse(assetID); _storePrice(witnetResponse); return lastGoodPrice; } function _getCurrentWitnetResponse(bytes32 _assetID) internal view returns(WitnetResponse memory response) { try witnet.valueFor(_assetID) returns ( int256 value, uint256 _timestamp, uint256 status ) { response.value = value; response._timestamp = _timestamp; response.status = status; } catch { // If call to Chainlink aggregator reverts, return a zero response with success = false return response; } } function _storePrice(WitnetResponse memory witnetResponse) internal { require(witnetResponse.status == 200, "witnet Response is not 200. response error."); uint goodPrice = _scaleWitnetPriceByDigits(uint(witnetResponse.value), 6); if (goodPrice != lastGoodPrice) { lastGoodPrice = goodPrice; emit LastGoodPriceUpdated(lastGoodPrice); } } function _scaleWitnetPriceByDigits(uint _price, uint _answerDigits) internal pure returns (uint) { /* * Convert the price returned by the Chainlink oracle to an 18-digit decimal for use by Liquity. * At date of Liquity launch, Chainlink uses an 8-digit price, but we also handle the possibility of * future changes. * */ uint price; if (_answerDigits >= TARGET_DIGITS) { // Scale the returned price value down to Liquity's target precision price = _price.div(10 ** (_answerDigits - TARGET_DIGITS)); } else if (_answerDigits < TARGET_DIGITS) { // Scale the returned price value up to Liquity's target precision price = _price.mul(10 ** (TARGET_DIGITS - _answerDigits)); } return price; } }
summary
Address: https://github.com/shanxuanch...
Generally speaking, there is no technical difficulty, just a regular step reading and writing task. Centralized Oracle service is relatively simple, but decentralization is very difficult. So far, there are nearly $300W TVL. Although the price of token fluctuates greatly, I am very confident in my heart. reason? Maybe I know all kinds of benefits in advance. If the token is unlocked, I think all the people who helped me climb over all the way will distribute some tokens. After thinking about it, maybe this is the only gift I can get before I go to Beijing.