From 8166ec0f06d2394c2c3bcd7ad1fd486c81bdb066 Mon Sep 17 00:00:00 2001 From: Aikdanai Sidhikosol Date: Mon, 30 Oct 2023 11:29:59 +0700 Subject: [PATCH] feat: add band oracle sample plugin --- plugins/BandOracle/configuration.yaml | 19 ++++ plugins/BandOracle/contract.sol | 157 ++++++++++++++++++++++++++ plugins/BandOracle/plugin.json | 7 ++ 3 files changed, 183 insertions(+) create mode 100644 plugins/BandOracle/configuration.yaml create mode 100644 plugins/BandOracle/contract.sol create mode 100644 plugins/BandOracle/plugin.json diff --git a/plugins/BandOracle/configuration.yaml b/plugins/BandOracle/configuration.yaml new file mode 100644 index 0000000..13ca320 --- /dev/null +++ b/plugins/BandOracle/configuration.yaml @@ -0,0 +1,19 @@ +contractName: "PacBandStdReferenceProxy" +constructor: +functions: + - name: setRate + arguments: + - BTC + - USDC + - 35000000000000000000000 +manage: + functions: + - name: setRate + arguments: + - name: base + type: string + - name: quote + type: string + - name: rate + type: uint256 +output: "BAND_ORACLE" diff --git a/plugins/BandOracle/contract.sol b/plugins/BandOracle/contract.sol new file mode 100644 index 0000000..fbb4ff5 --- /dev/null +++ b/plugins/BandOracle/contract.sol @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +/* + * @dev Provides information about the current execution context, including the + * sender of the transaction and its data. While these are generally available + * via msg.sender and msg.data, they should not be accessed in such a direct + * manner, since when dealing with GSN meta-transactions the account sending and + * paying for execution may not be the actual sender (as far as an application + * is concerned). + * + * This contract is only required for intermediate, library-like contracts. + */ +abstract contract Context { + function _msgSender() internal view virtual returns (address payable) { + return payable(msg.sender); + } + + function _msgData() internal view virtual returns (bytes memory) { + this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 + return msg.data; + } +} + +/** + * @dev Contract module which provides a basic access control mechanism, where + * there is an account (an owner) that can be granted exclusive access to + * specific functions. + * + * By default, the owner account will be the one that deploys the contract. This + * can later be changed with {transferOwnership}. + * + * This module is used through inheritance. It will make available the modifier + * onlyOwner, which can be applied to your functions to restrict their use to + * the owner. + */ +contract Ownable is Context { + address private _owner; + + event OwnershipTransferred( + address indexed previousOwner, + address indexed newOwner + ); + + /** + * @dev Initializes the contract setting the deployer as the initial owner. + */ + constructor() { + address msgSender = _msgSender(); + _owner = msgSender; + emit OwnershipTransferred(address(0), msgSender); + } + + /** + * @dev Returns the address of the current owner. + */ + function owner() public view returns (address) { + return _owner; + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(_owner == _msgSender(), "Ownable: caller is not the owner"); + _; + } + + /** + * @dev Leaves the contract without owner. It will not be possible to call + * onlyOwner functions anymore. Can only be called by the current owner. + * + * NOTE: Renouncing ownership will leave the contract without an owner, + * thereby removing any functionality that is only available to the owner. + */ + function renounceOwnership() public virtual onlyOwner { + emit OwnershipTransferred(_owner, address(0)); + _owner = address(0); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address newOwner) public virtual onlyOwner { + require( + newOwner != address(0), + "Ownable: new owner is the zero address" + ); + emit OwnershipTransferred(_owner, newOwner); + _owner = newOwner; + } +} + +interface IStdReference { + /// A structure returned whenever someone requests for standard reference data. + struct ReferenceData { + uint256 rate; // base/quote exchange rate, multiplied by 1e18. + uint256 lastUpdatedBase; // UNIX epoch of the last time when base price gets updated. + uint256 lastUpdatedQuote; // UNIX epoch of the last time when quote price gets updated. + } + + /// Returns the price data for the given base/quote pair. Revert if not available. + function getReferenceData( + string memory _base, + string memory _quote + ) external view returns (ReferenceData memory); + + /// Similar to getReferenceData, but with multiple base/quote pairs at once. + function getReferenceDataBulk( + string[] memory _bases, + string[] memory _quotes + ) external view returns (ReferenceData[] memory); +} + +contract PacBandStdReferenceProxy is Ownable, IStdReference { + mapping(string => mapping(string => uint256)) private _rates; + mapping(string => mapping(string => uint256)) private _lastUpdated; + + constructor() {} + + function setRate( + string memory _base, + string memory _quote, + uint256 _rate + ) public onlyOwner { + _rates[_base][_quote] = _rate; + _rates[_quote][_base] = (10 ** 36) / _rate; + _lastUpdated[_base][_quote] = block.timestamp; + _lastUpdated[_quote][_base] = block.timestamp; + } + + function getReferenceData( + string memory _base, + string memory _quote + ) public view override returns (ReferenceData memory) { + return + ReferenceData({ + rate: _rates[_base][_quote], + lastUpdatedBase: _lastUpdated[_base][_quote], + lastUpdatedQuote: _lastUpdated[_base][_quote] + }); + } + + function getReferenceDataBulk( + string[] memory _bases, + string[] memory _quotes + ) public view override returns (ReferenceData[] memory) { + require(_bases.length == _quotes.length, "BAD_INPUT_LENGTH"); + uint256 len = _bases.length; + ReferenceData[] memory results = new ReferenceData[](len); + for (uint256 idx = 0; idx < len; idx++) { + results[idx] = getReferenceData(_bases[idx], _quotes[idx]); + } + return results; + } +} diff --git a/plugins/BandOracle/plugin.json b/plugins/BandOracle/plugin.json new file mode 100644 index 0000000..280e0d3 --- /dev/null +++ b/plugins/BandOracle/plugin.json @@ -0,0 +1,7 @@ +{ + "name": "Band Std Reference", + "defaultDisplayName": "Band Std Reference", + "description": "Band Protocol standard price reference.", + "owner": "Band Protocol", + "url": "https://www.bandprotocol.com/" +}