编译器
0.8.13+commit.abaa5c0e
文件 1 的 9:AccessControl.sol
pragma solidity ^0.8.0;
import "IAccessControl.sol";
import "Context.sol";
import "Strings.sol";
import "ERC165.sol";
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
modifier onlyRole(bytes32 role) {
_checkRole(role, _msgSender());
_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(uint160(account), 20),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}
文件 2 的 9:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 3 的 9:ERC165.sol
pragma solidity ^0.8.0;
import "IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 4 的 9:IAccessControl.sol
pragma solidity ^0.8.0;
interface IAccessControl {
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
文件 5 的 9:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 6 的 9:IStdReference.sol
pragma solidity 0.8.13;
interface IStdReference {
struct ReferenceData {
uint256 rate;
uint256 lastUpdatedBase;
uint256 lastUpdatedQuote;
}
function getReferenceData(string memory _base, string memory _quote) external view returns (ReferenceData memory);
function getReferenceDataBulk(string[] memory _bases, string[] memory _quotes) external view returns (ReferenceData[] memory);
}
文件 7 的 9:StdReferenceBase.sol
pragma solidity 0.8.13;
import {IStdReference} from "IStdReference.sol";
abstract contract StdReferenceBase is IStdReference {
function getReferenceData(string memory _base, string memory _quote) public view virtual override returns (ReferenceData memory);
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;
}
}
文件 8 的 9:StdReferenceTick.sol
pragma solidity 0.8.13;
import {StdReferenceBase} from "StdReferenceBase.sol";
import {AccessControl} from "AccessControl.sol";
contract StdReferenceTick is AccessControl, StdReferenceBase {
bytes32 public constant RELAYER_ROLE = keccak256("RELAYER_ROLE");
bytes32 public constant LISTER_ROLE = keccak256("LISTER_ROLE");
bytes32 public constant DELISTER_ROLE = keccak256("DELISTER_ROLE");
bytes32 private constant USD = keccak256(bytes("USD"));
uint256 public constant MID_TICK = 262144;
struct Price {
uint256 tick;
string symbol;
}
uint256 public totalSymbolsCount = 0;
mapping(uint256 => uint256) public refs;
mapping(string => uint256) public symbolsToIDs;
mapping(uint256 => string) public idsToSymbols;
constructor(address admin) {
_grantRole(DEFAULT_ADMIN_ROLE, admin);
_grantRole(RELAYER_ROLE, admin);
_grantRole(LISTER_ROLE, admin);
_grantRole(DELISTER_ROLE, admin);
}
function _extractSlotTime(uint256 val) private pure returns (uint256 t) {
unchecked {
t = (val >> 225) & ((1 << 31) - 1);
}
}
function _extractSize(uint256 val) private pure returns (uint256 s) {
unchecked {
s = (val >> 222) & ((1 << 3) - 1);
}
}
function _extractTick(uint256 val, uint256 shiftLen) private pure returns (uint256 tick) {
unchecked {
tick = (val >> shiftLen) & ((1 << 19) - 1);
}
}
function _extractTimeOffset(uint256 val, uint256 shiftLen) private pure returns (uint256 offset) {
unchecked {
offset = (val >> shiftLen) & ((1 << 18) - 1);
}
}
function _setTime(uint256 val, uint256 time) private pure returns (uint256 newVal) {
unchecked {
newVal = (val & (type(uint256).max >> 31)) | (time << 225);
}
}
function _setSize(uint256 val, uint256 size) private pure returns (uint256 newVal) {
unchecked {
newVal = (val & ((type(uint256).max << (37 * (6 - size))) - ((((1 << 3) - 1)) << 222))) | (size << 222);
}
}
function _setTimeOffset(uint256 val, uint256 timeOffset, uint256 shiftLen) private pure returns (uint256 newVal) {
unchecked {
newVal = ((val & ~(uint256((1 << 18) - 1) << (shiftLen + 19))) | (timeOffset << (shiftLen + 19)));
}
}
function _setTicksAndTimeOffset(uint256 val, uint256 timeOffset, uint256 tick, uint256 shiftLen) private pure returns (uint256 newVal) {
unchecked {
newVal = (val & (~(uint256((1 << 37) - 1) << shiftLen))) | (((timeOffset << 19) | (tick & ((1 << 19) - 1))) << shiftLen);
}
}
function _getTickAndTime(uint256 slot, uint8 idx) private view returns (uint256 tick, uint256 lastUpdated) {
unchecked {
uint256 sVal = refs[slot];
uint256 idx_x_37 = idx * 37;
return (_extractTick(sVal, 185 - idx_x_37), _extractTimeOffset(sVal, 204 - idx_x_37) + _extractSlotTime(sVal));
}
}
function getSlotAndIndex(string memory symbol) public view returns (uint256 slot, uint8 idx) {
unchecked {
uint256 id = symbolsToIDs[symbol];
require(id != 0, "getSlotAndIndex: FAIL_SYMBOL_NOT_AVAILABLE");
return ((id - 1) / 6, uint8((id - 1) % 6));
}
}
function getTickAndTime(string memory symbol) public view returns (uint256 tick, uint256 lastUpdated) {
unchecked {
if (keccak256(bytes(symbol)) == USD) {
(tick, lastUpdated) = (MID_TICK, block.timestamp);
} else {
(uint256 slot, uint8 idx) = getSlotAndIndex(symbol);
(tick, lastUpdated) = _getTickAndTime(slot, idx);
require(tick != 0, "getTickAndTime: FAIL_TICK_0_IS_AN_EMPTY_PRICE");
}
}
}
function getReferenceData(string memory _base, string memory _quote) public view override returns (ReferenceData memory r) {
uint256 baseTick;
uint256 quoteTick;
(baseTick, r.lastUpdatedBase) = getTickAndTime(_base);
(quoteTick, r.lastUpdatedQuote) = getTickAndTime(_quote);
require(baseTick + MID_TICK > quoteTick, "getReferenceData: FAIL_PRICE_RATIO_TOO_LOW");
require(baseTick < MID_TICK + quoteTick, "getReferenceData: FAIL_PRICE_RATIO_TOO_HIGH");
r.rate = _getPriceFromTick((baseTick + MID_TICK) - quoteTick);
}
function _getPriceFromTick(uint256 x) private pure returns (uint256 y) {
unchecked {
require(x != 0, "_getPriceFromTick: FAIL_TICK_0_IS_AN_EMPTY_PRICE");
require(x < (1 << 19), "_getPriceFromTick: FAIL_TICK_OUT_OF_RANGE");
y = 649037107316853453566312041152512;
if (x < MID_TICK) {
x = MID_TICK - x;
if (x & 0x01 != 0) y = (y * 649102011027585138911668672356627) >> 109;
if (x & 0x02 != 0) y = (y * 649166921228687897425559839223862) >> 109;
if (x & 0x04 != 0) y = (y * 649296761104602847291923925447306) >> 109;
if (x & 0x08 != 0) y = (y * 649556518769447606681106054382372) >> 109;
if (x & 0x10 != 0) y = (y * 650076345896668132522271100656030) >> 109;
if (x & 0x20 != 0) y = (y * 651117248505878973533694452870408) >> 109;
if (x & 0x40 != 0) y = (y * 653204056474534657407624669811404) >> 109;
if (x & 0x80 != 0) y = (y * 657397758286396885483233885325217) >> 109;
if (x & 0x0100 != 0) y = (y * 665866108005128170549362417755489) >> 109;
if (x & 0x0200 != 0) y = (y * 683131470899774684431604377857106) >> 109;
if (x & 0x0400 != 0) y = (y * 719016834742958293196733842540130) >> 109;
if (x & 0x0800 != 0) y = (y * 796541835305874991615834691778664) >> 109;
if (x & 0x1000 != 0) y = (y * 977569522974447437629335387266319) >> 109;
if (x & 0x2000 != 0) y = (y * 1472399900522103311842374358851872) >> 109;
if (x & 0x4000 != 0) y = (y * 3340273526146976564083509455290620) >> 109;
if (x & 0x8000 != 0) y = (y * 17190738562859105750521122099339319) >> 109;
if (x & 0x010000 != 0) y = (y * 455322953040804340936374685561109626) >> 109;
if (x & 0x020000 != 0) y = (y * 319425483117388922324853186559947171877) >> 109;
y = 649037107316853453566312041152512000000000000000000 / y;
} else {
x = x - MID_TICK;
if (x & 0x01 != 0) y = (y * 649102011027585138911668672356627) >> 109;
if (x & 0x02 != 0) y = (y * 649166921228687897425559839223862) >> 109;
if (x & 0x04 != 0) y = (y * 649296761104602847291923925447306) >> 109;
if (x & 0x08 != 0) y = (y * 649556518769447606681106054382372) >> 109;
if (x & 0x10 != 0) y = (y * 650076345896668132522271100656030) >> 109;
if (x & 0x20 != 0) y = (y * 651117248505878973533694452870408) >> 109;
if (x & 0x40 != 0) y = (y * 653204056474534657407624669811404) >> 109;
if (x & 0x80 != 0) y = (y * 657397758286396885483233885325217) >> 109;
if (x & 0x0100 != 0) y = (y * 665866108005128170549362417755489) >> 109;
if (x & 0x0200 != 0) y = (y * 683131470899774684431604377857106) >> 109;
if (x & 0x0400 != 0) y = (y * 719016834742958293196733842540130) >> 109;
if (x & 0x0800 != 0) y = (y * 796541835305874991615834691778664) >> 109;
if (x & 0x1000 != 0) y = (y * 977569522974447437629335387266319) >> 109;
if (x & 0x2000 != 0) y = (y * 1472399900522103311842374358851872) >> 109;
if (x & 0x4000 != 0) y = (y * 3340273526146976564083509455290620) >> 109;
if (x & 0x8000 != 0) y = (y * 17190738562859105750521122099339319) >> 109;
if (x & 0x010000 != 0) y = (y * 455322953040804340936374685561109626) >> 109;
if (x & 0x020000 != 0) y = (y * 319425483117388922324853186559947171877) >> 109;
y = (y * 1e18) / 649037107316853453566312041152512;
}
}
}
function getPriceFromTick(uint256 x) public pure returns (uint256 y) {
y = _getPriceFromTick(x);
}
function grantRelayers(address[] calldata accounts) external onlyRole(getRoleAdmin(RELAYER_ROLE)) {
for (uint256 idx = 0; idx < accounts.length; idx++) {
_grantRole(RELAYER_ROLE, accounts[idx]);
}
}
function revokeRelayers(address[] calldata accounts) external onlyRole(getRoleAdmin(RELAYER_ROLE)) {
for (uint256 idx = 0; idx < accounts.length; idx++) {
_revokeRole(RELAYER_ROLE, accounts[idx]);
}
}
function listing(string[] calldata symbols) public onlyRole(LISTER_ROLE) {
require(symbols.length != 0, "listing: FAIL_SYMBOLS_IS_EMPTY");
uint256 _totalSymbolsCount = totalSymbolsCount;
uint256 sid = _totalSymbolsCount / 6;
uint256 sVal = refs[sid];
uint256 sSize = _extractSize(sVal);
for (uint256 i = 0; i < symbols.length; i++) {
require(keccak256(bytes(symbols[i])) != USD, "listing: FAIL_USD_CANT_BE_SET");
require(symbolsToIDs[symbols[i]] == 0, "listing: FAIL_SYMBOL_IS_ALREADY_SET");
uint256 slotID = _totalSymbolsCount / 6;
_totalSymbolsCount++;
symbolsToIDs[symbols[i]] = _totalSymbolsCount;
idsToSymbols[_totalSymbolsCount] = symbols[i];
if (sid != slotID) {
refs[sid] = sVal;
sid = slotID;
sVal = refs[sid];
sSize = _extractSize(sVal);
}
sSize++;
sVal = _setSize(sVal, sSize);
}
refs[sid] = sVal;
totalSymbolsCount = _totalSymbolsCount;
}
function delisting(string[] calldata symbols) public onlyRole(DELISTER_ROLE) {
uint256 _totalSymbolsCount = totalSymbolsCount;
uint256 slotID1;
uint256 slotID2;
uint256 sVal1;
uint256 sVal2;
uint256 sSize;
uint256 shiftLen;
uint256 lastSegment;
uint256 time;
string memory lastSymbol;
for (uint256 i = 0; i < symbols.length; i++) {
uint256 id = symbolsToIDs[symbols[i]];
require(id != 0, "delisting: FAIL_SYMBOL_NOT_AVAILABLE");
lastSymbol = idsToSymbols[_totalSymbolsCount];
symbolsToIDs[lastSymbol] = id;
idsToSymbols[id] = lastSymbol;
slotID1 = (_totalSymbolsCount - 1) / 6;
slotID2 = (id - 1) / 6;
sVal1 = refs[slotID1];
sSize = _extractSize(sVal1);
lastSegment = (sVal1 >> (37 * (6 - sSize))) & ((1 << 37) - 1);
shiftLen = 37 * (5 - ((id - 1) % 6));
if (slotID1 == slotID2) {
sVal1 = (sVal1 & (type(uint256).max - (((1 << 37) - 1) << shiftLen))) | (lastSegment << shiftLen);
} else {
sVal2 = refs[slotID2];
time = _extractSlotTime(sVal1) + (lastSegment >> 19);
require(time >= _extractSlotTime(sVal2), "delisting: FAIL_LAST_TIMESTAMP_IS_LESS_THAN_TARGET_TIMESTAMP");
time -= _extractSlotTime(sVal2);
require(time < 1 << 18, "delisting: FAIL_DELTA_TIME_EXCEED_3_DAYS");
lastSegment = (time << 19) | (lastSegment & ((1 << 19) - 1));
refs[slotID2] = (sVal2 & (type(uint256).max - (((1 << 37) - 1) << shiftLen))) | (lastSegment << shiftLen);
}
refs[slotID1] = _setSize(sVal1, sSize - 1);
delete symbolsToIDs[symbols[i]];
delete idsToSymbols[_totalSymbolsCount];
_totalSymbolsCount--;
}
totalSymbolsCount = _totalSymbolsCount;
}
function relay(uint256 time, uint256 requestID, Price[] calldata ps) external onlyRole(RELAYER_ROLE) {
unchecked {
uint256 id;
uint256 sid = type(uint256).max;
uint256 nextSID;
uint256 sTime;
uint256 sVal;
uint256 shiftLen;
for (uint256 i = 0; i < ps.length; i++) {
id = symbolsToIDs[ps[i].symbol];
require(id != 0, "relay: FAIL_SYMBOL_NOT_AVAILABLE");
nextSID = (id - 1) / 6;
if (sid != nextSID) {
if (sVal != 0) refs[sid] = sVal;
sVal = refs[nextSID];
sid = nextSID;
sTime = _extractSlotTime(sVal);
}
shiftLen = 204 - (37 * ((id - 1) % 6));
if (sTime + _extractTimeOffset(sVal, shiftLen) < time) {
require(time < sTime + (1 << 18), "relay: FAIL_DELTA_TIME_EXCEED_3_DAYS");
sVal = _setTicksAndTimeOffset(sVal, time - sTime, ps[i].tick, shiftLen - 19);
}
}
if (sVal != 0) refs[sid] = sVal;
}
}
function relayRebase(uint256 time, uint256 requestID, Price[] calldata ps) external onlyRole(RELAYER_ROLE) {
unchecked {
uint256 id;
uint256 nextID;
uint256 sVal;
uint256 sTime;
uint256 sSize;
uint256 shiftLen;
uint256 timeOffset;
uint256 i;
while (i < ps.length) {
id = symbolsToIDs[ps[i].symbol];
require(id != 0, "relayRebase: FAIL_SYMBOL_NOT_AVAILABLE");
require((id - 1) % 6 == 0, "relayRebase: FAIL_INVALID_FIRST_IDX");
sVal = refs[(id - 1) / 6];
(sTime, sSize) = (_extractSlotTime(sVal), _extractSize(sVal));
require(sTime < time, "relayRebase: FAIL_NEW_TIME_<=_CURRENT");
shiftLen = 204;
timeOffset = _extractTimeOffset(sVal, shiftLen);
shiftLen = shiftLen - 19;
sVal = sTime + timeOffset <= time
? _setTicksAndTimeOffset(sVal, 0, ps[i].tick, shiftLen)
: _setTimeOffset(sVal, (sTime + timeOffset) - time, shiftLen);
require(i + sSize <= ps.length, "relayRebase: FAIL_INCONSISTENT_SIZES");
for (uint256 j = i + 1; j < i + sSize; j++) {
nextID = symbolsToIDs[ps[j].symbol];
require(nextID != 0, "relayRebase: FAIL_SYMBOL_NOT_AVAILABLE");
require(nextID + i == id + j, "relayRebase: FAIL_INVALID_IDX_ORDER");
shiftLen = shiftLen - 18;
timeOffset = _extractTimeOffset(sVal, shiftLen);
shiftLen = shiftLen - 19;
sVal = sTime + timeOffset <= time
? _setTicksAndTimeOffset(sVal, 0, ps[j].tick, shiftLen)
: _setTimeOffset(sVal, (sTime + timeOffset) - time, shiftLen);
}
refs[(id - 1) / 6] = _setTime(sVal, time);
i += sSize;
}
}
}
}
文件 9 的 9:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
{
"compilationTarget": {
"StdReferenceTick.sol": "StdReferenceTick"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DELISTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LISTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MID_TICK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAYER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string[]","name":"symbols","type":"string[]"}],"name":"delisting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"getPriceFromTick","outputs":[{"internalType":"uint256","name":"y","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"string","name":"_base","type":"string"},{"internalType":"string","name":"_quote","type":"string"}],"name":"getReferenceData","outputs":[{"components":[{"internalType":"uint256","name":"rate","type":"uint256"},{"internalType":"uint256","name":"lastUpdatedBase","type":"uint256"},{"internalType":"uint256","name":"lastUpdatedQuote","type":"uint256"}],"internalType":"struct IStdReference.ReferenceData","name":"r","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string[]","name":"_bases","type":"string[]"},{"internalType":"string[]","name":"_quotes","type":"string[]"}],"name":"getReferenceDataBulk","outputs":[{"components":[{"internalType":"uint256","name":"rate","type":"uint256"},{"internalType":"uint256","name":"lastUpdatedBase","type":"uint256"},{"internalType":"uint256","name":"lastUpdatedQuote","type":"uint256"}],"internalType":"struct IStdReference.ReferenceData[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"symbol","type":"string"}],"name":"getSlotAndIndex","outputs":[{"internalType":"uint256","name":"slot","type":"uint256"},{"internalType":"uint8","name":"idx","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"symbol","type":"string"}],"name":"getTickAndTime","outputs":[{"internalType":"uint256","name":"tick","type":"uint256"},{"internalType":"uint256","name":"lastUpdated","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"grantRelayers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"idsToSymbols","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string[]","name":"symbols","type":"string[]"}],"name":"listing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"refs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"uint256","name":"requestID","type":"uint256"},{"components":[{"internalType":"uint256","name":"tick","type":"uint256"},{"internalType":"string","name":"symbol","type":"string"}],"internalType":"struct StdReferenceTick.Price[]","name":"ps","type":"tuple[]"}],"name":"relay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"uint256","name":"requestID","type":"uint256"},{"components":[{"internalType":"uint256","name":"tick","type":"uint256"},{"internalType":"string","name":"symbol","type":"string"}],"internalType":"struct StdReferenceTick.Price[]","name":"ps","type":"tuple[]"}],"name":"relayRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"revokeRelayers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"symbolsToIDs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSymbolsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]