pragma solidity 0.6.7;
contract GebMath {
uint256 public constant RAY = 10 ** 27;
uint256 public constant WAD = 10 ** 18;
function ray(uint x) public pure returns (uint z) {
z = multiply(x, 10 ** 9);
}
function rad(uint x) public pure returns (uint z) {
z = multiply(x, 10 ** 27);
}
function minimum(uint x, uint y) public pure returns (uint z) {
z = (x <= y) ? x : y;
}
function addition(uint x, uint y) public pure returns (uint z) {
z = x + y;
require(z >= x, "uint-uint-add-overflow");
}
function subtract(uint x, uint y) public pure returns (uint z) {
z = x - y;
require(z <= x, "uint-uint-sub-underflow");
}
function multiply(uint x, uint y) public pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x, "uint-uint-mul-overflow");
}
function rmultiply(uint x, uint y) public pure returns (uint z) {
z = multiply(x, y) / RAY;
}
function rdivide(uint x, uint y) public pure returns (uint z) {
z = multiply(x, RAY) / y;
}
function wdivide(uint x, uint y) public pure returns (uint z) {
z = multiply(x, WAD) / y;
}
function wmultiply(uint x, uint y) public pure returns (uint z) {
z = multiply(x, y) / WAD;
}
function rpower(uint x, uint n, uint base) public pure returns (uint z) {
assembly {
switch x case 0 {switch n case 0 {z := base} default {z := 0}}
default {
switch mod(n, 2) case 0 { z := base } default { z := x }
let half := div(base, 2) // for rounding.
for { n := div(n, 2) } n { n := div(n,2) } {
let xx := mul(x, x)
if iszero(eq(div(xx, x), x)) { revert(0,0) }
let xxRound := add(xx, half)
if lt(xxRound, xx) { revert(0,0) }
x := div(xxRound, base)
if mod(n,2) {
let zx := mul(z, x)
if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { revert(0,0) }
let zxRound := add(zx, half)
if lt(zxRound, zx) { revert(0,0) }
z := div(zxRound, base)
}
}
}
}
}
}
abstract contract OracleLike {
function getResultWithValidity() virtual external view returns (uint256, bool);
}
abstract contract PIDCalculator {
function computeRate(uint256, uint256, uint256) virtual external returns (uint256);
function rt(uint256, uint256, uint256) virtual external view returns (uint256);
function pscl() virtual external view returns (uint256);
function tlv() virtual external view returns (uint256);
}
contract PIRateSetter is GebMath {
// --- Auth ---
mapping (address => uint) public authorizedAccounts;
/**
* @notice Add auth to an account
* @param account Account to add auth to
*/
function addAuthorization(address account) external isAuthorized {
authorizedAccounts[account] = 1;
emit AddAuthorization(account);
}
/**
* @notice Remove auth from an account
* @param account Account to remove auth from
*/
function removeAuthorization(address account) external isAuthorized {
authorizedAccounts[account] = 0;
emit RemoveAuthorization(account);
}
/**
* @notice Checks whether msg.sender can call an authed function
**/
modifier isAuthorized {
require(authorizedAccounts[msg.sender] == 1, "PIRateSetter/account-not-authorized");
_;
}
// --- Variables ---
// When the price feed was last updated
uint256 public lastUpdateTime; // [timestamp]
// Enforced gap between calls
uint256 public updateRateDelay; // [seconds]
// Whether the leak is set to zero by default
uint256 public defaultLeak; // [0 or 1]
// --- System Dependencies ---
// OSM or medianizer for the system coin
OracleLike public orcl;
// OracleRelayer where the redemption price is stored
OracleRelayerLike public oracleRelayer;
// The contract that will pass the new redemption rate to the oracle relayer
SetterRelayer public setterRelayer;
// Calculator for the redemption rate
PIDCalculator public pidCalculator;
// --- Events ---
event AddAuthorization(address account);
event RemoveAuthorization(address account);
event ModifyParameters(
bytes32 parameter,
address addr
);
event ModifyParameters(
bytes32 parameter,
uint256 val
);
event UpdateRedemptionRate(
uint marketPrice,
uint redemptionPrice,
uint redemptionRate
);
event FailUpdateRedemptionRate(
uint marketPrice,
uint redemptionPrice,
uint redemptionRate,
bytes reason
);
constructor(
address oracleRelayer_,
address setterRelayer_,
address orcl_,
address pidCalculator_,
uint256 updateRateDelay_
) public {
require(oracleRelayer_ != address(0), "PIRateSetter/null-oracle-relayer");
require(setterRelayer_ != address(0), "PIRateSetter/null-setter-relayer");
require(orcl_ != address(0), "PIRateSetter/null-orcl");
require(pidCalculator_ != address(0), "PIRateSetter/null-calculator");
authorizedAccounts[msg.sender] = 1;
defaultLeak = 1;
oracleRelayer = OracleRelayerLike(oracleRelayer_);
setterRelayer = SetterRelayer(setterRelayer_);
orcl = OracleLike(orcl_);
pidCalculator = PIDCalculator(pidCalculator_);
updateRateDelay = updateRateDelay_;
emit AddAuthorization(msg.sender);
emit ModifyParameters("orcl", orcl_);
emit ModifyParameters("oracleRelayer", oracleRelayer_);
emit ModifyParameters("setterRelayer", setterRelayer_);
emit ModifyParameters("pidCalculator", pidCalculator_);
emit ModifyParameters("updateRateDelay", updateRateDelay_);
}
// --- Boolean Logic ---
function either(bool x, bool y) internal pure returns (bool z) {
assembly{ z := or(x, y)}
}
// --- Management ---
/*
* @notify Modify the address of a contract that the setter is connected to
* @param parameter Contract name
* @param addr The new contract address
*/
function modifyParameters(bytes32 parameter, address addr) external isAuthorized {
require(addr != address(0), "PIRateSetter/null-addr");
if (parameter == "orcl") orcl = OracleLike(addr);
else if (parameter == "oracleRelayer") oracleRelayer = OracleRelayerLike(addr);
else if (parameter == "setterRelayer") setterRelayer = SetterRelayer(addr);
else if (parameter == "pidCalculator") {
pidCalculator = PIDCalculator(addr);
}
else revert("PIRateSetter/modify-unrecognized-param");
emit ModifyParameters(
parameter,
addr
);
}
/*
* @notify Modify a uint256 parameter
* @param parameter The parameter name
* @param val The new parameter value
*/
function modifyParameters(bytes32 parameter, uint256 val) external isAuthorized {
if (parameter == "updateRateDelay") {
require(val > 0, "PIRateSetter/null-update-delay");
updateRateDelay = val;
}
else if (parameter == "defaultLeak") {
require(val <= 1, "PIRateSetter/invalid-default-leak");
defaultLeak = val;
}
else revert("PIRateSetter/modify-unrecognized-param");
emit ModifyParameters(
parameter,
val
);
}
// --- Feedback Mechanism ---
/**
* @notice Compute and set a new redemption rate
* @param feeReceiver The proposed address that should receive the reward for calling this function
* (unless it's address(0) in which case msg.sender will get it)
**/
function updateRate(address feeReceiver) external {
// The fee receiver must not be null
require(feeReceiver != address(0), "PIRateSetter/null-fee-receiver");
// Check delay between calls
require(either(subtract(now, lastUpdateTime) >= updateRateDelay, lastUpdateTime == 0), "PIRateSetter/wait-more");
// Get price feed updates
(uint256 marketPrice, bool hasValidValue) = orcl.getResultWithValidity();
// If the oracle has a value
require(hasValidValue, "PIRateSetter/invalid-oracle-value");
// If the price is non-zero
require(marketPrice > 0, "PIRateSetter/null-price");
// Get the latest redemption price
uint redemptionPrice = oracleRelayer.redemptionPrice();
// Calculate the rate
uint256 iapcr = (defaultLeak == 1) ? RAY : rpower(pidCalculator.pscl(), pidCalculator.tlv(), RAY);
uint256 calculated = pidCalculator.computeRate(
marketPrice,
redemptionPrice,
iapcr
);
// Store the timestamp of the update
lastUpdateTime = now;
// Update the rate using the setter relayer
try setterRelayer.relayRate(calculated, feeReceiver) {
// Emit success event
emit UpdateRedemptionRate(
ray(marketPrice),
redemptionPrice,
calculated
);
}
catch(bytes memory revertReason) {
emit FailUpdateRedemptionRate(
ray(marketPrice),
redemptionPrice,
calculated,
revertReason
);
}
}
// --- Getters ---
/**
* @notice Get the market price from the system coin oracle
**/
function getMarketPrice() external view returns (uint256) {
(uint256 marketPrice, ) = orcl.getResultWithValidity();
return marketPrice;
}
/**
* @notice Get the redemption and the market prices for the system coin
**/
function getRedemptionAndMarketPrices() external returns (uint256 marketPrice, uint256 redemptionPrice) {
(marketPrice, ) = orcl.getResultWithValidity();
redemptionPrice = oracleRelayer.redemptionPrice();
}
}
abstract contract StabilityFeeTreasuryLike {
function getAllowance(address) virtual external view returns (uint, uint);
function systemCoin() virtual external view returns (address);
function pullFunds(address, address, uint) virtual external;
function setTotalAllowance(address, uint256) external virtual;
function setPerBlockAllowance(address, uint256) external virtual;
}
contract IncreasingTreasuryReimbursement is GebMath {
// --- Auth ---
mapping (address => uint) public authorizedAccounts;
/**
* @notice Add auth to an account
* @param account Account to add auth to
*/
function addAuthorization(address account) virtual external isAuthorized {
authorizedAccounts[account] = 1;
emit AddAuthorization(account);
}
/**
* @notice Remove auth from an account
* @param account Account to remove auth from
*/
function removeAuthorization(address account) virtual external isAuthorized {
authorizedAccounts[account] = 0;
emit RemoveAuthorization(account);
}
/**
* @notice Checks whether msg.sender can call an authed function
**/
modifier isAuthorized {
require(authorizedAccounts[msg.sender] == 1, "IncreasingTreasuryReimbursement/account-not-authorized");
_;
}
// --- Variables ---
// Starting reward for the fee receiver/keeper
uint256 public baseUpdateCallerReward; // [wad]
// Max possible reward for the fee receiver/keeper
uint256 public maxUpdateCallerReward; // [wad]
// Max delay taken into consideration when calculating the adjusted reward
uint256 public maxRewardIncreaseDelay; // [seconds]
// Rate applied to baseUpdateCallerReward every extra second passed beyond a certain point (e.g next time when a specific function needs to be called)
uint256 public perSecondCallerRewardIncrease; // [ray]
// SF treasury
StabilityFeeTreasuryLike public treasury;
// --- Events ---
event AddAuthorization(address account);
event RemoveAuthorization(address account);
event ModifyParameters(
bytes32 parameter,
address addr
);
event ModifyParameters(
bytes32 parameter,
uint256 val
);
event FailRewardCaller(bytes revertReason, address feeReceiver, uint256 amount);
constructor(
address treasury_,
uint256 baseUpdateCallerReward_,
uint256 maxUpdateCallerReward_,
uint256 perSecondCallerRewardIncrease_
) public {
if (address(treasury_) != address(0)) {
require(StabilityFeeTreasuryLike(treasury_).systemCoin() != address(0), "IncreasingTreasuryReimbursement/treasury-coin-not-set");
}
require(maxUpdateCallerReward_ >= baseUpdateCallerReward_, "IncreasingTreasuryReimbursement/invalid-max-caller-reward");
require(perSecondCallerRewardIncrease_ >= RAY, "IncreasingTreasuryReimbursement/invalid-per-second-reward-increase");
authorizedAccounts[msg.sender] = 1;
treasury = StabilityFeeTreasuryLike(treasury_);
baseUpdateCallerReward = baseUpdateCallerReward_;
maxUpdateCallerReward = maxUpdateCallerReward_;
perSecondCallerRewardIncrease = perSecondCallerRewardIncrease_;
maxRewardIncreaseDelay = uint(-1);
emit AddAuthorization(msg.sender);
emit ModifyParameters("treasury", treasury_);
emit ModifyParameters("baseUpdateCallerReward", baseUpdateCallerReward);
emit ModifyParameters("maxUpdateCallerReward", maxUpdateCallerReward);
emit ModifyParameters("perSecondCallerRewardIncrease", perSecondCallerRewardIncrease);
}
// --- Boolean Logic ---
function either(bool x, bool y) internal pure returns (bool z) {
assembly{ z := or(x, y)}
}
// --- Treasury ---
/**
* @notice This returns the stability fee treasury allowance for this contract by taking the minimum between the per block and the total allowances
**/
function treasuryAllowance() public view returns (uint256) {
(uint total, uint perBlock) = treasury.getAllowance(address(this));
return minimum(total, perBlock);
}
/*
* @notice Get the SF reward that can be sent to a function caller right now
* @param timeOfLastUpdate The last time when the function that the treasury pays for has been updated
* @param defaultDelayBetweenCalls Enforced delay between calls to the function for which the treasury reimburses callers
*/
function getCallerReward(uint256 timeOfLastUpdate, uint256 defaultDelayBetweenCalls) public view returns (uint256) {
// If the rewards are null or if the time of the last update is in the future or present, return 0
bool nullRewards = (baseUpdateCallerReward == 0 && maxUpdateCallerReward == 0);
if (either(timeOfLastUpdate >= now, nullRewards)) return 0;
// If the time elapsed is smaller than defaultDelayBetweenCalls or if the base reward is zero, return 0
uint256 timeElapsed = (timeOfLastUpdate == 0) ? defaultDelayBetweenCalls : subtract(now, timeOfLastUpdate);
if (either(timeElapsed < defaultDelayBetweenCalls, baseUpdateCallerReward == 0)) {
return 0;
}
// If too much time elapsed, return the max reward
uint256 adjustedTime = subtract(timeElapsed, defaultDelayBetweenCalls);
uint256 maxPossibleReward = minimum(maxUpdateCallerReward, treasuryAllowance() / RAY);
if (adjustedTime > maxRewardIncreaseDelay) {
return maxPossibleReward;
}
// Calculate the reward
uint256 calculatedReward = baseUpdateCallerReward;
if (adjustedTime > 0) {
calculatedReward = rmultiply(rpower(perSecondCallerRewardIncrease, adjustedTime, RAY), calculatedReward);
}
// If the reward is higher than max, set it to max
if (calculatedReward > maxPossibleReward) {
calculatedReward = maxPossibleReward;
}
return calculatedReward;
}
/**
* @notice Send a stability fee reward to an address
* @param proposedFeeReceiver The SF receiver
* @param reward The system coin amount to send
**/
function rewardCaller(address proposedFeeReceiver, uint256 reward) internal {
// If the receiver is the treasury itself or if the treasury is null or if the reward is zero, return
if (address(treasury) == proposedFeeReceiver) return;
if (either(address(treasury) == address(0), reward == 0)) return;
// Determine the actual receiver and send funds
address finalFeeReceiver = (proposedFeeReceiver == address(0)) ? msg.sender : proposedFeeReceiver;
try treasury.pullFunds(finalFeeReceiver, treasury.systemCoin(), reward) {}
catch(bytes memory revertReason) {
emit FailRewardCaller(revertReason, finalFeeReceiver, reward);
}
}
}
abstract contract OracleRelayerLike {
function redemptionPrice() virtual external returns (uint256);
function modifyParameters(bytes32,uint256) virtual external;
}
contract SetterRelayer is IncreasingTreasuryReimbursement {
// --- Events ---
event RelayRate(address setter, uint256 redemptionRate);
// --- Variables ---
// When the rate has last been relayed
uint256 public lastUpdateTime; // [timestamp]
// Enforced gap between relays
uint256 public relayDelay; // [seconds]
// The address that's allowed to pass new redemption rates
address public setter;
// The oracle relayer contract
OracleRelayerLike public oracleRelayer;
constructor(
address oracleRelayer_,
address treasury_,
uint256 baseUpdateCallerReward_,
uint256 maxUpdateCallerReward_,
uint256 perSecondCallerRewardIncrease_,
uint256 relayDelay_
) public IncreasingTreasuryReimbursement(treasury_, baseUpdateCallerReward_, maxUpdateCallerReward_, perSecondCallerRewardIncrease_) {
relayDelay = relayDelay_;
oracleRelayer = OracleRelayerLike(oracleRelayer_);
emit ModifyParameters("relayDelay", relayDelay_);
}
// --- Administration ---
/*
* @notice Change the addresses of contracts that this relayer is connected to
* @param parameter The contract whose address is changed
* @param addr The new contract address
*/
function modifyParameters(bytes32 parameter, address addr) external isAuthorized {
require(addr != address(0), "SetterRelayer/null-addr");
if (parameter == "setter") {
setter = addr;
}
else if (parameter == "treasury") {
require(StabilityFeeTreasuryLike(addr).systemCoin() != address(0), "SetterRelayer/treasury-coin-not-set");
treasury = StabilityFeeTreasuryLike(addr);
}
else revert("SetterRelayer/modify-unrecognized-param");
emit ModifyParameters(
parameter,
addr
);
}
/*
* @notify Modify a uint256 parameter
* @param parameter The parameter name
* @param val The new parameter value
*/
function modifyParameters(bytes32 parameter, uint256 val) external isAuthorized {
if (parameter == "baseUpdateCallerReward") {
require(val <= maxUpdateCallerReward, "SetterRelayer/invalid-base-caller-reward");
baseUpdateCallerReward = val;
}
else if (parameter == "maxUpdateCallerReward") {
require(val >= baseUpdateCallerReward, "SetterRelayer/invalid-max-caller-reward");
maxUpdateCallerReward = val;
}
else if (parameter == "perSecondCallerRewardIncrease") {
require(val >= RAY, "SetterRelayer/invalid-caller-reward-increase");
perSecondCallerRewardIncrease = val;
}
else if (parameter == "maxRewardIncreaseDelay") {
require(val > 0, "SetterRelayer/invalid-max-increase-delay");
maxRewardIncreaseDelay = val;
}
else if (parameter == "relayDelay") {
relayDelay = val;
}
else revert("SetterRelayer/modify-unrecognized-param");
emit ModifyParameters(
parameter,
val
);
}
// --- Core Logic ---
/*
* @notice Relay a new redemption rate to the OracleRelayer
* @param redemptionRate The new redemption rate to relay
*/
function relayRate(uint256 redemptionRate, address feeReceiver) external {
// Perform checks
require(setter == msg.sender, "SetterRelayer/invalid-caller");
require(feeReceiver != address(0), "SetterRelayer/null-fee-receiver");
require(feeReceiver != setter, "SetterRelayer/setter-cannot-receive-fees");
// Check delay between calls
require(either(subtract(now, lastUpdateTime) >= relayDelay, lastUpdateTime == 0), "SetterRelayer/wait-more");
// Get the caller's reward
uint256 callerReward = getCallerReward(lastUpdateTime, relayDelay);
// Store the timestamp of the update
lastUpdateTime = now;
// Update the redemption price and then set the rate
oracleRelayer.redemptionPrice();
oracleRelayer.modifyParameters("redemptionRate", redemptionRate);
// Emit an event
emit RelayRate(setter, redemptionRate);
// Pay the caller for relaying the rate
rewardCaller(feeReceiver, callerReward);
}
}
{
"compilationTarget": {
"PIRateSetter.sol": "PIRateSetter"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"oracleRelayer_","type":"address"},{"internalType":"address","name":"setterRelayer_","type":"address"},{"internalType":"address","name":"orcl_","type":"address"},{"internalType":"address","name":"pidCalculator_","type":"address"},{"internalType":"uint256","name":"updateRateDelay_","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"AddAuthorization","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"marketPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"redemptionPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"redemptionRate","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"reason","type":"bytes"}],"name":"FailUpdateRedemptionRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"parameter","type":"bytes32"},{"indexed":false,"internalType":"address","name":"addr","type":"address"}],"name":"ModifyParameters","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"parameter","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"val","type":"uint256"}],"name":"ModifyParameters","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"RemoveAuthorization","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"marketPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"redemptionPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"redemptionRate","type":"uint256"}],"name":"UpdateRedemptionRate","type":"event"},{"inputs":[],"name":"RAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WAD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"addition","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"authorizedAccounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultLeak","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMarketPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRedemptionAndMarketPrices","outputs":[{"internalType":"uint256","name":"marketPrice","type":"uint256"},{"internalType":"uint256","name":"redemptionPrice","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"minimum","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"parameter","type":"bytes32"},{"internalType":"address","name":"addr","type":"address"}],"name":"modifyParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"parameter","type":"bytes32"},{"internalType":"uint256","name":"val","type":"uint256"}],"name":"modifyParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"multiply","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"oracleRelayer","outputs":[{"internalType":"contract OracleRelayerLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"orcl","outputs":[{"internalType":"contract OracleLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pidCalculator","outputs":[{"internalType":"contract PIDCalculator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"rad","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"ray","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"rdivide","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"rmultiply","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"n","type":"uint256"},{"internalType":"uint256","name":"base","type":"uint256"}],"name":"rpower","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"setterRelayer","outputs":[{"internalType":"contract SetterRelayer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"subtract","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"feeReceiver","type":"address"}],"name":"updateRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateRateDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"wdivide","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"wmultiply","outputs":[{"internalType":"uint256","name":"z","type":"uint256"}],"stateMutability":"pure","type":"function"}]