Address Contract Partially Verified
Address
0x7Acfc14dBF2decD1c9213Db32AE7784626daEb48
Balance
0 ETH
Nonce
1
Code Size
5149 bytes
Creator
0xa57A4e61...262E at tx 0xa1dddb57...4c6098
Indexed Transactions
0 (1 on-chain, 0.8% indexed)
Contract Bytecode
5149 bytes
0x608060405234801561001057600080fd5b50600436106101c45760003560e01c806363c9f725116100f9578063d6e882dc11610097578063f435899f11610071578063f435899f14610458578063f74826bb14610460578063f752fdc314610486578063fe4f5890146104a9576101c4565b8063d6e882dc14610404578063dd2d2a121461042d578063ddf0b81314610450576101c4565b80636a146024116100d35780636a146024146103ab57806394f3f81d146103b3578063a0871637146103d9578063c8f33c91146103fc576101c4565b806363c9f7251461036f578063660e16c3146103775780636614f0101461037f576101c4565b8063448a2638116101665780634faf61ab116101405780634faf61ab1461031b57806354f363a314610323578063552033c41461034657806363ac7ca71461034e576101c4565b8063448a2638146102d257806346f3e81c146102f65780634a8d632c14610313576101c4565b806324ba5884116101a257806324ba58841461023e57806335b28153146102645780633c8bb3e61461028c5780633ef5e445146102af576101c4565b8063056640b7146101c957806310213447146101fe578063165c4a161461021b575b600080fd5b6101ec600480360360408110156101df57600080fd5b50803590602001356104cc565b60408051918252519081900360200190f35b6101ec6004803603602081101561021457600080fd5b50356104f4565b6101ec6004803603604081101561023157600080fd5b508035906020013561050a565b6101ec6004803603602081101561025457600080fd5b50356001600160a01b031661056f565b61028a6004803603602081101561027a57600080fd5b50356001600160a01b0316610581565b005b6101ec600480360360408110156102a257600080fd5b5080359060200135610621565b6101ec600480360360408110156102c557600080fd5b5080359060200135610636565b6102da61068e565b604080516001600160a01b039092168252519081900360200190f35b6101ec6004803603602081101561030c57600080fd5b503561069d565b6102da6106b5565b6102da6106c4565b6101ec6004803603604081101561033957600080fd5b50803590602001356106d3565b6101ec610724565b610356610734565b6040805192835260208301919091528051918290030190f35b6101ec610820565b6101ec610826565b61028a6004803603604081101561039557600080fd5b50803590602001356001600160a01b031661089c565b6101ec610a93565b61028a600480360360208110156103c957600080fd5b50356001600160a01b0316610a9f565b6101ec600480360360408110156103ef57600080fd5b5080359060200135610b3e565b6101ec610b57565b6101ec6004803603606081101561041a57600080fd5b5080359060208101359060400135610b5d565b6101ec6004803603604081101561044357600080fd5b5080359060200135610c1b565b6101ec610c34565b6102da610c3a565b61028a6004803603602081101561047657600080fd5b50356001600160a01b0316610c49565b6101ec6004803603604081101561049c57600080fd5b50803590602001356111e1565b61028a600480360360408110156104bf57600080fd5b50803590602001356111f6565b60006b033b2e3c9fd0803ce80000006104e5848461050a565b816104ec57fe5b049392505050565b600061050482633b9aca0061050a565b92915050565b60008115806105255750508082028282828161052257fe5b04145b610504576040805162461bcd60e51b815260206004820152601660248201527575696e742d75696e742d6d756c2d6f766572666c6f7760501b604482015290519081900360640190fd5b60006020819052908152604090205481565b336000908152602081905260409020546001146105cf5760405162461bcd60e51b815260040180806020018281038252602381526020018061139f6023913960400191505060405180910390fd5b6001600160a01b0381166000818152602081815260409182902060019055815192835290517f599a298163e1678bb1c676052a8930bf0b8a1261ed6e01b8a2391e55f70001029281900390910190a150565b6000670de0b6b3a76400006104e5848461050a565b80820382811115610504576040805162461bcd60e51b815260206004820152601760248201527f75696e742d75696e742d7375622d756e646572666c6f77000000000000000000604482015290519081900360640190fd5b6007546001600160a01b031681565b6000610504826b033b2e3c9fd0803ce800000061050a565b6004546001600160a01b031681565b6005546001600160a01b031681565b81810182811015610504576040805162461bcd60e51b815260206004820152601660248201527575696e742d75696e742d6164642d6f766572666c6f7760501b604482015290519081900360640190fd5b6b033b2e3c9fd0803ce800000081565b60048054604080516309fa15b560e31b8152815160009485946001600160a01b031693634fd0ada89380830193919290829003018186803b15801561077857600080fd5b505afa15801561078c573d6000803e3d6000fd5b505050506040513d60408110156107a257600080fd5b505160055460408051630316dd2360e61b815290519294506001600160a01b039091169163c5b748c0916004808201926020929091908290030181600087803b1580156107ee57600080fd5b505af1158015610802573d6000803e3d6000fd5b505050506040513d602081101561081857600080fd5b505191929050565b60025481565b60048054604080516309fa15b560e31b8152815160009485946001600160a01b031693634fd0ada89380830193919290829003018186803b15801561086a57600080fd5b505afa15801561087e573d6000803e3d6000fd5b505050506040513d604081101561089457600080fd5b505191505090565b336000908152602081905260409020546001146108ea5760405162461bcd60e51b815260040180806020018281038252602381526020018061139f6023913960400191505060405180910390fd5b6001600160a01b03811661093e576040805162461bcd60e51b81526020600482015260166024820152752824a930ba32a9b2ba3a32b917b73ab63616b0b2323960511b604482015290519081900360640190fd5b81631bdc98db60e21b141561096d57600480546001600160a01b0319166001600160a01b038316179055610a4c565b816c37b930b1b632a932b630bcb2b960991b14156109a557600580546001600160a01b0319166001600160a01b038316179055610a4c565b816c39b2ba3a32b92932b630bcb2b960991b14156109dd57600680546001600160a01b0319166001600160a01b038316179055610a4c565b816c3834b221b0b631bab630ba37b960991b1415610a1557600780546001600160a01b0319166001600160a01b038316179055610a4c565b60405162461bcd60e51b81526004018080602001828103825260268152602001806113c26026913960400191505060405180910390fd5b604080518381526001600160a01b038316602082015281517fd91f38cf03346b5dc15fb60f9076f866295231ad3c3841a1051f8443f25170d1929181900390910190a15050565b670de0b6b3a764000081565b33600090815260208190526040902054600114610aed5760405162461bcd60e51b815260040180806020018281038252602381526020018061139f6023913960400191505060405180910390fd5b6001600160a01b03811660008181526020818152604080832092909255815192835290517f8834a87e641e9716be4f34527af5d23e11624f1ddeefede6ad75a9acfc31b9039281900390910190a150565b6000816104e5846b033b2e3c9fd0803ce800000061050a565b60015481565b6000838015610bfd57600184168015610b7857859250610b7c565b8392505b50600283046002850494505b8415610bf7578586028687820414610b9f57600080fd5b81810181811015610baf57600080fd5b8590049650506001851615610bec578583028387820414158715151615610bd557600080fd5b81810181811015610be557600080fd5b8590049350505b600285049450610b88565b50610c13565b838015610c0d5760009250610c11565b8392505b505b509392505050565b600081831115610c2b5781610c2d565b825b9392505050565b60035481565b6006546001600160a01b031681565b6001600160a01b038116610ca4576040805162461bcd60e51b815260206004820152601e60248201527f5049526174655365747465722f6e756c6c2d6665652d72656365697665720000604482015290519081900360640190fd5b610cc3600254610cb642600154610636565b1015600154600014611358565b610d0d576040805162461bcd60e51b81526020600482015260166024820152755049526174655365747465722f776169742d6d6f726560501b604482015290519081900360640190fd5b60048054604080516309fa15b560e31b8152815160009485946001600160a01b031693634fd0ada89380830193919290829003018186803b158015610d5157600080fd5b505afa158015610d65573d6000803e3d6000fd5b505050506040513d6040811015610d7b57600080fd5b508051602090910151909250905080610dc55760405162461bcd60e51b815260040180806020018281038252602181526020018061137e6021913960400191505060405180910390fd5b60008211610e1a576040805162461bcd60e51b815260206004820152601760248201527f5049526174655365747465722f6e756c6c2d7072696365000000000000000000604482015290519081900360640190fd5b60055460408051630316dd2360e61b815290516000926001600160a01b03169163c5b748c091600480830192602092919082900301818787803b158015610e6057600080fd5b505af1158015610e74573d6000803e3d6000fd5b505050506040513d6020811015610e8a57600080fd5b5051600354909150600090600114610f965760075460408051630be3617360e31b81529051610f91926001600160a01b031691635f1b0b98916004808301926020929190829003018186803b158015610ee257600080fd5b505afa158015610ef6573d6000803e3d6000fd5b505050506040513d6020811015610f0c57600080fd5b505160075460408051636e3126ef60e01b815290516001600160a01b0390921691636e3126ef91600480820192602092909190829003018186803b158015610f5357600080fd5b505afa158015610f67573d6000803e3d6000fd5b505050506040513d6020811015610f7d57600080fd5b50516b033b2e3c9fd0803ce8000000610b5d565b610fa4565b6b033b2e3c9fd0803ce80000005b600754604080516338e3899760e11b815260048101889052602481018690526044810184905290519293506000926001600160a01b03909216916371c7132e9160648082019260209290919082900301818787803b15801561100557600080fd5b505af1158015611019573d6000803e3d6000fd5b505050506040513d602081101561102f57600080fd5b505142600155600654604080516359426fad60e01b8152600481018490526001600160a01b038a8116602483015291519394509116916359426fad9160448082019260009290919082900301818387803b15801561108c57600080fd5b505af192505050801561109d575060015b611190573d8080156110cb576040519150601f19603f3d011682016040523d82523d6000602084013e6110d0565b606091505b507f878358802301ac1f0e23e8ed16d4ab85e7fb999aef9e41643301346986421bf96110fb876104f4565b8584846040518085815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561114d578181015183820152602001611135565b50505050905090810190601f16801561117a5780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a1506111d9565b7f16abce12916e67b821a9cdabe7103d806d6f4280a69d5830925b3e34c83f52a86111ba866104f4565b6040805191825260208201869052818101849052519081900360600190a15b505050505050565b6000816104e584670de0b6b3a764000061050a565b336000908152602081905260409020546001146112445760405162461bcd60e51b815260040180806020018281038252602381526020018061139f6023913960400191505060405180910390fd5b816e7570646174655261746544656c617960881b14156112bd57600081116112b3576040805162461bcd60e51b815260206004820152601e60248201527f5049526174655365747465722f6e756c6c2d7570646174652d64656c61790000604482015290519081900360640190fd5b6002819055611319565b816a64656661756c744c65616b60a81b1415610a155760018111156113135760405162461bcd60e51b815260040180806020018281038252602181526020018061135d6021913960400191505060405180910390fd5b60038190555b604080518381526020810183905281517fac7c5c1afaef770ec56ac6268cd3f2fbb1035858ead2601d6553157c33036c3a929181900390910190a15050565b179056fe5049526174655365747465722f696e76616c69642d64656661756c742d6c65616b5049526174655365747465722f696e76616c69642d6f7261636c652d76616c75655049526174655365747465722f6163636f756e742d6e6f742d617574686f72697a65645049526174655365747465722f6d6f646966792d756e7265636f676e697a65642d706172616da2646970667358221220ed465aafb9a8fba6b1987565e7f97fa6cf6dae083fc27a5d0ed0b2cd21b9ced764736f6c63430006070033
Verified Source Code Partial Match
Compiler: v0.6.7+commit.b8d736ae
EVM: istanbul
Optimization: Yes (200 runs)
PIRateSetter.sol 548 lines
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);
}
}
Read Contract
RAY 0x552033c4 → uint256
WAD 0x6a146024 → uint256
addition 0x54f363a3 → uint256
authorizedAccounts 0x24ba5884 → uint256
defaultLeak 0xddf0b813 → uint256
getMarketPrice 0x660e16c3 → uint256
lastUpdateTime 0xc8f33c91 → uint256
minimum 0xdd2d2a12 → uint256
multiply 0x165c4a16 → uint256
oracleRelayer 0x4faf61ab → address
orcl 0x4a8d632c → address
pidCalculator 0x448a2638 → address
rad 0x46f3e81c → uint256
ray 0x10213447 → uint256
rdivide 0xa0871637 → uint256
rmultiply 0x056640b7 → uint256
rpower 0xd6e882dc → uint256
setterRelayer 0xf435899f → address
subtract 0x3ef5e445 → uint256
updateRateDelay 0x63c9f725 → uint256
wdivide 0xf752fdc3 → uint256
wmultiply 0x3c8bb3e6 → uint256
Write Contract 6 functions
These functions modify contract state and require a wallet transaction to execute.
addAuthorization 0x35b28153
address account
getRedemptionAndMarketPrices 0x63ac7ca7
No parameters
returns: uint256, uint256
modifyParameters 0x6614f010
bytes32 parameter
address addr
modifyParameters 0xfe4f5890
bytes32 parameter
uint256 val
removeAuthorization 0x94f3f81d
address account
updateRate 0xf74826bb
address feeReceiver
Recent Transactions
This address has 1 on-chain transactions, but only 0.8% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →