Transaction Hash:
Block:
21605282 at Jan-12-2025 02:00:23 AM +UTC
Transaction Fee:
0.000533471953998236 ETH
$1.09
Gas Used:
226,228 Gas / 2.358116387 Gwei
Emitted Events:
| 307 |
OSM.LogValue( val=0000000000000000000000000000000000000000000000B336A5EA108BBE8000 )
|
| 308 |
OSM.0x1817835800000000000000000000000000000000000000000000000000000000( 0x1817835800000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000e717ec34b2707fc8c226b34be5eae8482d06ed03, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 1817835800000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
|
| 309 |
OSM.LogValue( val=0000000000000000000000000000000000000000000013EC601B569C4B140000 )
|
| 310 |
OSM.0x1817835800000000000000000000000000000000000000000000000000000000( 0x1817835800000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000e717ec34b2707fc8c226b34be5eae8482d06ed03, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 1817835800000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
|
| 311 |
OSM_STETHUSD.LogValue( val=0000000000000000000000000000000000000000000000D46086B96EE0700CE6 )
|
| 312 |
OSM_STETHUSD.0x1817835800000000000000000000000000000000000000000000000000000000( 0x1817835800000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000e717ec34b2707fc8c226b34be5eae8482d06ed03, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 1817835800000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
|
| 313 |
OSM.LogValue( val=00000000000000000000000000000000000000000000004E716FBF5C05BE0000 )
|
| 314 |
OSM.0x1817835800000000000000000000000000000000000000000000000000000000( 0x1817835800000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000e717ec34b2707fc8c226b34be5eae8482d06ed03, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 1817835800000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
|
| 315 |
OracleJob.Work( 0x0d83c9346002c9fca728d3a5d743e61837b6479c5773ba8c8ade72febabf4fca, 0x4d414b4552000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000060, 0000000000000000000000000000000000000000000000000000000000000100, 0000000000000000000000000000000000000000000000000000000000000004, 0000000000000000000000000000000000000000000000000000000000000004, 4554482d41000000000000000000000000000000000000000000000000000000, 574254432d410000000000000000000000000000000000000000000000000000, 5753544554482d41000000000000000000000000000000000000000000000000, 4c53452d4d4b522d410000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
|
0x4838B106...B0BAD5f97
Miner
| (Titan Builder) | 11.210232280533551461 Eth | 11.210233456919151461 Eth | 0.0000011763856 | |
| 0x4F94e33D...28551C56b | |||||
| 0x81FE72B5...9A9B85763 | (Sky: PIP ETH) | ||||
| 0xCb4FadD1...3d0E3C969 |
0.968861847133301364 Eth
Nonce: 13474
|
0.968328375179303128 Eth
Nonce: 13475
| 0.000533471953998236 | ||
| 0xf185d068...3CC5C6C42 | (Sky: PIP WBTC) | ||||
| 0xFe7a2aC0...84D9f043F | (Sky: PIP wstETH) |
Execution Trace
OracleJob.work( network=4D414B4552000000000000000000000000000000000000000000000000000000, args=0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000E000000000000000000000000000000000000000000000000000000000000000044554482D41000000000000000000000000000000000000000000000000000000574254432D4100000000000000000000000000000000000000000000000000005753544554482D410000000000000000000000000000000000000000000000004C53452D4D4B522D4100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 )
-
Sequencer.isMaster( network=4D414B4552000000000000000000000000000000000000000000000000000000 ) => ( True ) -
Vat.ilks( 4554482D41000000000000000000000000000000000000000000000000000000 ) => ( Art=257810302198499830894461289, rate=1212553606107802115576497079, spot=2279934482758620689655172413793, line=467308034846975007882323061518947147643428474950016096, dust=7500000000000000000000000000000000000000000000000 ) -
IlkRegistry.pip( ilk=4554482D41000000000000000000000000000000000000000000000000000000 ) => ( 0x81FE72B5A8d1A857d176C3E7d5Bd2679A9B85763 ) OSM.CALL( )-
MedianETHUSD.STATICCALL( )
-
-
Vat.ilks( 574254432D410000000000000000000000000000000000000000000000000000 ) => ( Art=39896645370515278068641055, rate=1227025670741892651405103653, spot=62723546666666666666666666666666, line=0, dust=7500000000000000000000000000000000000000000000000 ) -
IlkRegistry.pip( ilk=574254432D410000000000000000000000000000000000000000000000000000 ) => ( 0xf185d0682d50819263941e5f4EacC763CC5C6C42 ) OSM.CALL( )-
MedianBTCUSD.STATICCALL( )
-
-
Vat.ilks( 5753544554482D41000000000000000000000000000000000000000000000000 ) => ( Art=67450756700576654956234905, rate=1165025181813024533887686988, spot=2611776796124538822126666666666, line=115649229897926050978575358665945619446871603888621929, dust=7500000000000000000000000000000000000000000000000 ) -
IlkRegistry.pip( ilk=5753544554482D41000000000000000000000000000000000000000000000000 ) => ( 0xFe7a2aC0B945f12089aEEB6eCebf4F384D9f043F ) OSM_STETHUSD.CALL( )-
MedianWSTETHUSD.STATICCALL( )
-
-
Vat.ilks( 4C53452D4D4B522D410000000000000000000000000000000000000000000000 ) => ( Art=19593230968405515965791076, rate=1023634434771541692722430950, spot=723510000000000000000000000000, line=20000000000000000000000000000000000000000000000000000, dust=30000000000000000000000000000000000000000000000000 ) -
IlkRegistry.pip( ilk=4C53452D4D4B522D410000000000000000000000000000000000000000000000 ) => ( 0x4F94e33D0D74CfF5Ca0D3a66F1A650628551C56b ) OSM.CALL( )-
MedianMKRUSD.STATICCALL( )
-
work[OracleJob (ln:92)]
isMaster[OracleJob (ln:93)]NotMaster[OracleJob (ln:93)]decode[OracleJob (ln:95)]ilks[OracleJob (ln:99)]pip[OracleJob (ln:101)]poke[OracleJob (ln:102)]ilks[OracleJob (ln:109)]poke[OracleJob (ln:111)]ilks[OracleJob (ln:112)]NotSuccessful[OracleJob (ln:118)]Work[OracleJob (ln:120)]
File 1 of 12: OracleJob
File 2 of 12: OSM
File 3 of 12: OSM
File 4 of 12: OSM_STETHUSD
File 5 of 12: OSM
File 6 of 12: Sequencer
File 7 of 12: Vat
File 8 of 12: IlkRegistry
File 9 of 12: MedianETHUSD
File 10 of 12: MedianBTCUSD
File 11 of 12: MedianWSTETHUSD
File 12 of 12: MedianMKRUSD
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2022 Dai Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pragma solidity 0.8.13;
/// @title Maker Keeper Network Job
/// @notice A job represents an independant unit of work that can be done by a keeper
interface IJob {
/// @notice Executes this unit of work
/// @dev Should revert iff workable() returns canWork of false
/// @param network The name of the external keeper network
/// @param args Custom arguments supplied to the job, should be copied from workable response
function work(bytes32 network, bytes calldata args) external;
/// @notice Ask this job if it has a unit of work available
/// @dev This should never revert, only return false if nothing is available
/// @dev This should normally be a view, but sometimes that's not possible
/// @param network The name of the external keeper network
/// @return canWork Returns true if a unit of work is available
/// @return args The custom arguments to be provided to work() or an error string if canWork is false
function workable(bytes32 network) external returns (bool canWork, bytes memory args);
}
interface SequencerLike {
function isMaster(bytes32 network) external view returns (bool);
}
interface IlkRegistryLike {
function list() external view returns (bytes32[] memory);
function pip(bytes32 ilk) external view returns (address);
}
interface VatLike {
function ilks(bytes32 ilk) external view returns (
uint256 Art,
uint256 rate,
uint256 spot,
uint256 line,
uint256 dust
);
}
interface PokeLike {
function poke() external;
}
interface SpotterLike {
function vat() external view returns (address);
function poke(bytes32 ilk) external;
}
/// @title Triggers osm / oracle updates for all ilks
contract OracleJob is IJob {
SequencerLike public immutable sequencer;
IlkRegistryLike public immutable ilkRegistry;
VatLike public immutable vat;
SpotterLike public immutable spotter;
// Don't actually store anything
bytes32[] private toPoke;
bytes32[] private spotterIlksToPoke;
// --- Errors ---
error NotMaster(bytes32 network);
error NotSuccessful();
// --- Events ---
event Work(bytes32 indexed network, bytes32[] toPoke, bytes32[] spotterIlksToPoke, uint256 numSuccessful);
constructor(address _sequencer, address _ilkRegistry, address _spotter) {
sequencer = SequencerLike(_sequencer);
ilkRegistry = IlkRegistryLike(_ilkRegistry);
spotter = SpotterLike(_spotter);
vat = VatLike(spotter.vat());
}
function work(bytes32 network, bytes calldata args) external override {
if (!sequencer.isMaster(network)) revert NotMaster(network);
(bytes32[] memory _toPoke, bytes32[] memory _spotterIlksToPoke) = abi.decode(args, (bytes32[], bytes32[]));
uint256 numSuccessful = 0;
for (uint256 i = 0; i < _toPoke.length; i++) {
bytes32 ilk = _toPoke[i];
(uint256 Art,,, uint256 line,) = vat.ilks(ilk);
if (Art == 0 && line == 0) continue;
PokeLike pip = PokeLike(ilkRegistry.pip(ilk));
try pip.poke() {
numSuccessful++;
} catch {
}
}
for (uint256 i = 0; i < _spotterIlksToPoke.length; i++) {
bytes32 ilk = _spotterIlksToPoke[i];
(uint256 Art,, uint256 beforeSpot, uint256 line,) = vat.ilks(ilk);
if (Art == 0 && line == 0) continue;
spotter.poke(ilk);
(,, uint256 afterSpot,,) = vat.ilks(ilk);
if (beforeSpot != afterSpot) {
numSuccessful++;
}
}
if (numSuccessful == 0) revert NotSuccessful();
emit Work(network, _toPoke, _spotterIlksToPoke, numSuccessful);
}
function workable(bytes32 network) external override returns (bool, bytes memory) {
if (!sequencer.isMaster(network)) return (false, bytes("Network is not master"));
delete toPoke;
delete spotterIlksToPoke;
bytes32[] memory ilks = ilkRegistry.list();
for (uint256 i = 0; i < ilks.length; i++) {
bytes32 ilk = ilks[i];
PokeLike pip = PokeLike(ilkRegistry.pip(ilk));
if (address(pip) == address(0)) continue;
(uint256 Art,, uint256 beforeSpot, uint256 line,) = vat.ilks(ilk);
if (Art == 0 && line == 0) continue; // Skip if no debt / line
// Just try to poke the oracle and add to the list if it works
// This won't add an OSM twice
try pip.poke() {
toPoke.push(ilk);
} catch {
}
// See if the spot price changes
spotter.poke(ilk);
(,, uint256 afterSpot,,) = vat.ilks(ilk);
if (beforeSpot != afterSpot) {
spotterIlksToPoke.push(ilk);
}
}
if (toPoke.length > 0 || spotterIlksToPoke.length > 0) {
return (true, abi.encode(toPoke, spotterIlksToPoke));
} else {
return (false, bytes("No ilks ready"));
}
}
}File 2 of 12: OSM
// osm.sol - Oracle Security Module
// Copyright (C) 2019 Maker Foundation
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
contract DSAuthority {
function canCall(
address src, address dst, bytes4 sig
) public view returns (bool);
}
contract DSAuthEvents {
event LogSetAuthority (address indexed authority);
event LogSetOwner (address indexed owner);
}
contract DSAuth is DSAuthEvents {
DSAuthority public authority;
address public owner;
constructor() public {
owner = msg.sender;
emit LogSetOwner(msg.sender);
}
function setOwner(address owner_)
public
auth
{
owner = owner_;
emit LogSetOwner(owner);
}
function setAuthority(DSAuthority authority_)
public
auth
{
authority = authority_;
emit LogSetAuthority(address(authority));
}
modifier auth {
require(isAuthorized(msg.sender, msg.sig), "ds-auth-unauthorized");
_;
}
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
if (src == address(this)) {
return true;
} else if (src == owner) {
return true;
} else if (authority == DSAuthority(0)) {
return false;
} else {
return authority.canCall(src, address(this), sig);
}
}
}
////// lib/ds-stop/lib/ds-note/src/note.sol
/// note.sol -- the `note' modifier, for logging calls as events
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/* pragma solidity >=0.4.23; */
contract DSNote {
event LogNote(
bytes4 indexed sig,
address indexed guy,
bytes32 indexed foo,
bytes32 indexed bar,
uint256 wad,
bytes fax
) anonymous;
modifier note {
bytes32 foo;
bytes32 bar;
uint256 wad;
assembly {
foo := calldataload(4)
bar := calldataload(36)
wad := callvalue
}
emit LogNote(msg.sig, msg.sender, foo, bar, wad, msg.data);
_;
}
}
////// lib/ds-value/lib/ds-thing/lib/ds-math/src/math.sol
/// math.sol -- mixin for inline numerical wizardry
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/* pragma solidity >0.4.13; */
contract DSMath {
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x, "ds-math-add-overflow");
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x, "ds-math-sub-underflow");
}
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow");
}
function min(uint x, uint y) internal pure returns (uint z) {
return x <= y ? x : y;
}
function max(uint x, uint y) internal pure returns (uint z) {
return x >= y ? x : y;
}
function imin(int x, int y) internal pure returns (int z) {
return x <= y ? x : y;
}
function imax(int x, int y) internal pure returns (int z) {
return x >= y ? x : y;
}
uint constant WAD = 10 ** 18;
uint constant RAY = 10 ** 27;
function wmul(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, y), WAD / 2) / WAD;
}
function rmul(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, y), RAY / 2) / RAY;
}
function wdiv(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, WAD), y / 2) / y;
}
function rdiv(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, RAY), y / 2) / y;
}
// This famous algorithm is called "exponentiation by squaring"
// and calculates x^n with x as fixed-point and n as regular unsigned.
//
// It's O(log n), instead of O(n) for naive repeated multiplication.
//
// These facts are why it works:
//
// If n is even, then x^n = (x^2)^(n/2).
// If n is odd, then x^n = x * x^(n-1),
// and applying the equation for even x gives
// x^n = x * (x^2)^((n-1) / 2).
//
// Also, EVM division is flooring and
// floor[(n-1) / 2] = floor[n / 2].
//
function rpow(uint x, uint n) internal pure returns (uint z) {
z = n % 2 != 0 ? x : RAY;
for (n /= 2; n != 0; n /= 2) {
x = rmul(x, x);
if (n % 2 != 0) {
z = rmul(z, x);
}
}
}
}
////// lib/ds-value/lib/ds-thing/src/thing.sol
// thing.sol - `auth` with handy mixins. your things should be DSThings
// Copyright (C) 2017 DappHub, LLC
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/* pragma solidity >=0.4.23; */
/* import 'ds-auth/auth.sol'; */
/* import 'ds-note/note.sol'; */
/* import 'ds-math/math.sol'; */
contract DSThing is DSAuth, DSNote, DSMath {
function S(string memory s) internal pure returns (bytes4) {
return bytes4(keccak256(abi.encodePacked(s)));
}
}
////// lib/ds-value/src/value.sol
/// value.sol - a value is a simple thing, it can be get and set
// Copyright (C) 2017 DappHub, LLC
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/* pragma solidity >=0.4.23; */
/* import 'ds-thing/thing.sol'; */
contract DSValue is DSThing {
bool has;
bytes32 val;
function peek() public view returns (bytes32, bool) {
return (val,has);
}
function read() public view returns (bytes32) {
bytes32 wut; bool haz;
(wut, haz) = peek();
require(haz, "haz-not");
return wut;
}
function poke(bytes32 wut) public note auth {
val = wut;
has = true;
}
function void() public note auth { // unset the value
has = false;
}
}
////// src/osm.sol
/* pragma solidity >=0.5.10; */
/* import "ds-value/value.sol"; */
contract LibNote {
event LogNote(
bytes4 indexed sig,
address indexed usr,
bytes32 indexed arg1,
bytes32 indexed arg2,
bytes data
) anonymous;
modifier note {
_;
assembly {
// log an 'anonymous' event with a constant 6 words of calldata
// and four indexed topics: selector, caller, arg1 and arg2
let mark := msize // end of memory ensures zero
mstore(0x40, add(mark, 288)) // update free memory pointer
mstore(mark, 0x20) // bytes type data offset
mstore(add(mark, 0x20), 224) // bytes size (padded)
calldatacopy(add(mark, 0x40), 0, 224) // bytes payload
log4(mark, 288, // calldata
shl(224, shr(224, calldataload(0))), // msg.sig
caller, // msg.sender
calldataload(4), // arg1
calldataload(36) // arg2
)
}
}
}
contract OSM is LibNote {
// --- Auth ---
mapping (address => uint) public wards;
function rely(address usr) external note auth { wards[usr] = 1; }
function deny(address usr) external note auth { wards[usr] = 0; }
modifier auth {
require(wards[msg.sender] == 1, "OSM/not-authorized");
_;
}
// --- Stop ---
uint256 public stopped;
modifier stoppable { require(stopped == 0, "OSM/is-stopped"); _; }
// --- Math ---
function add(uint64 x, uint64 y) internal pure returns (uint64 z) {
z = x + y;
require(z >= x);
}
address public src;
uint16 constant ONE_HOUR = uint16(3600);
uint16 public hop = ONE_HOUR;
uint64 public zzz;
struct Feed {
uint128 val;
uint128 has;
}
Feed cur;
Feed nxt;
// Whitelisted contracts, set by an auth
mapping (address => uint256) public bud;
modifier toll { require(bud[msg.sender] == 1, "OSM/contract-not-whitelisted"); _; }
event LogValue(bytes32 val);
constructor (address src_) public {
wards[msg.sender] = 1;
src = src_;
}
function stop() external note auth {
stopped = 1;
}
function start() external note auth {
stopped = 0;
}
function change(address src_) external note auth {
src = src_;
}
function era() internal view returns (uint) {
return block.timestamp;
}
function prev(uint ts) internal view returns (uint64) {
require(hop != 0, "OSM/hop-is-zero");
return uint64(ts - (ts % hop));
}
function step(uint16 ts) external auth {
require(ts > 0, "OSM/ts-is-zero");
hop = ts;
}
function void() external note auth {
cur = nxt = Feed(0, 0);
stopped = 1;
}
function pass() public view returns (bool ok) {
return era() >= add(zzz, hop);
}
function poke() external note stoppable {
require(pass(), "OSM/not-passed");
(bytes32 wut, bool ok) = DSValue(src).peek();
if (ok) {
cur = nxt;
nxt = Feed(uint128(uint(wut)), 1);
zzz = prev(era());
emit LogValue(bytes32(uint(cur.val)));
}
}
function peek() external view toll returns (bytes32,bool) {
return (bytes32(uint(cur.val)), cur.has == 1);
}
function peep() external view toll returns (bytes32,bool) {
return (bytes32(uint(nxt.val)), nxt.has == 1);
}
function read() external view toll returns (bytes32) {
require(cur.has == 1, "OSM/no-current-value");
return (bytes32(uint(cur.val)));
}
function kiss(address a) external note auth {
require(a != address(0), "OSM/no-contract-0");
bud[a] = 1;
}
function diss(address a) external note auth {
bud[a] = 0;
}
function kiss(address[] calldata a) external note auth {
for(uint i = 0; i < a.length; i++) {
require(a[i] != address(0), "OSM/no-contract-0");
bud[a[i]] = 1;
}
}
function diss(address[] calldata a) external note auth {
for(uint i = 0; i < a.length; i++) {
bud[a[i]] = 0;
}
}
}File 3 of 12: OSM
/**
*Submitted for verification at Etherscan.io on 2019-11-13
*/
// osm.sol - Oracle Security Module
// Copyright (C) 2019 Maker Foundation
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
contract DSAuthority {
function canCall(
address src, address dst, bytes4 sig
) public view returns (bool);
}
contract DSAuthEvents {
event LogSetAuthority (address indexed authority);
event LogSetOwner (address indexed owner);
}
contract DSAuth is DSAuthEvents {
DSAuthority public authority;
address public owner;
constructor() public {
owner = msg.sender;
emit LogSetOwner(msg.sender);
}
function setOwner(address owner_)
public
auth
{
owner = owner_;
emit LogSetOwner(owner);
}
function setAuthority(DSAuthority authority_)
public
auth
{
authority = authority_;
emit LogSetAuthority(address(authority));
}
modifier auth {
require(isAuthorized(msg.sender, msg.sig), "ds-auth-unauthorized");
_;
}
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
if (src == address(this)) {
return true;
} else if (src == owner) {
return true;
} else if (authority == DSAuthority(0)) {
return false;
} else {
return authority.canCall(src, address(this), sig);
}
}
}
////// lib/ds-stop/lib/ds-note/src/note.sol
/// note.sol -- the `note' modifier, for logging calls as events
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/* pragma solidity >=0.4.23; */
contract DSNote {
event LogNote(
bytes4 indexed sig,
address indexed guy,
bytes32 indexed foo,
bytes32 indexed bar,
uint256 wad,
bytes fax
) anonymous;
modifier note {
bytes32 foo;
bytes32 bar;
uint256 wad;
assembly {
foo := calldataload(4)
bar := calldataload(36)
wad := callvalue
}
emit LogNote(msg.sig, msg.sender, foo, bar, wad, msg.data);
_;
}
}
////// lib/ds-value/lib/ds-thing/lib/ds-math/src/math.sol
/// math.sol -- mixin for inline numerical wizardry
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/* pragma solidity >0.4.13; */
contract DSMath {
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x, "ds-math-add-overflow");
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x, "ds-math-sub-underflow");
}
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow");
}
function min(uint x, uint y) internal pure returns (uint z) {
return x <= y ? x : y;
}
function max(uint x, uint y) internal pure returns (uint z) {
return x >= y ? x : y;
}
function imin(int x, int y) internal pure returns (int z) {
return x <= y ? x : y;
}
function imax(int x, int y) internal pure returns (int z) {
return x >= y ? x : y;
}
uint constant WAD = 10 ** 18;
uint constant RAY = 10 ** 27;
function wmul(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, y), WAD / 2) / WAD;
}
function rmul(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, y), RAY / 2) / RAY;
}
function wdiv(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, WAD), y / 2) / y;
}
function rdiv(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, RAY), y / 2) / y;
}
// This famous algorithm is called "exponentiation by squaring"
// and calculates x^n with x as fixed-point and n as regular unsigned.
//
// It's O(log n), instead of O(n) for naive repeated multiplication.
//
// These facts are why it works:
//
// If n is even, then x^n = (x^2)^(n/2).
// If n is odd, then x^n = x * x^(n-1),
// and applying the equation for even x gives
// x^n = x * (x^2)^((n-1) / 2).
//
// Also, EVM division is flooring and
// floor[(n-1) / 2] = floor[n / 2].
//
function rpow(uint x, uint n) internal pure returns (uint z) {
z = n % 2 != 0 ? x : RAY;
for (n /= 2; n != 0; n /= 2) {
x = rmul(x, x);
if (n % 2 != 0) {
z = rmul(z, x);
}
}
}
}
////// lib/ds-value/lib/ds-thing/src/thing.sol
// thing.sol - `auth` with handy mixins. your things should be DSThings
// Copyright (C) 2017 DappHub, LLC
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/* pragma solidity >=0.4.23; */
/* import 'ds-auth/auth.sol'; */
/* import 'ds-note/note.sol'; */
/* import 'ds-math/math.sol'; */
contract DSThing is DSAuth, DSNote, DSMath {
function S(string memory s) internal pure returns (bytes4) {
return bytes4(keccak256(abi.encodePacked(s)));
}
}
////// lib/ds-value/src/value.sol
/// value.sol - a value is a simple thing, it can be get and set
// Copyright (C) 2017 DappHub, LLC
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/* pragma solidity >=0.4.23; */
/* import 'ds-thing/thing.sol'; */
contract DSValue is DSThing {
bool has;
bytes32 val;
function peek() public view returns (bytes32, bool) {
return (val,has);
}
function read() public view returns (bytes32) {
bytes32 wut; bool haz;
(wut, haz) = peek();
require(haz, "haz-not");
return wut;
}
function poke(bytes32 wut) public note auth {
val = wut;
has = true;
}
function void() public note auth { // unset the value
has = false;
}
}
////// src/osm.sol
/* pragma solidity >=0.5.10; */
/* import "ds-value/value.sol"; */
contract LibNote {
event LogNote(
bytes4 indexed sig,
address indexed usr,
bytes32 indexed arg1,
bytes32 indexed arg2,
bytes data
) anonymous;
modifier note {
_;
assembly {
// log an 'anonymous' event with a constant 6 words of calldata
// and four indexed topics: selector, caller, arg1 and arg2
let mark := msize // end of memory ensures zero
mstore(0x40, add(mark, 288)) // update free memory pointer
mstore(mark, 0x20) // bytes type data offset
mstore(add(mark, 0x20), 224) // bytes size (padded)
calldatacopy(add(mark, 0x40), 0, 224) // bytes payload
log4(mark, 288, // calldata
shl(224, shr(224, calldataload(0))), // msg.sig
caller, // msg.sender
calldataload(4), // arg1
calldataload(36) // arg2
)
}
}
}
contract OSM is LibNote {
// --- Auth ---
mapping (address => uint) public wards;
function rely(address usr) external note auth { wards[usr] = 1; }
function deny(address usr) external note auth { wards[usr] = 0; }
modifier auth {
require(wards[msg.sender] == 1, "OSM/not-authorized");
_;
}
// --- Stop ---
uint256 public stopped;
modifier stoppable { require(stopped == 0, "OSM/is-stopped"); _; }
// --- Math ---
function add(uint64 x, uint64 y) internal pure returns (uint64 z) {
z = x + y;
require(z >= x);
}
address public src;
uint16 constant ONE_HOUR = uint16(3600);
uint16 public hop = ONE_HOUR;
uint64 public zzz;
struct Feed {
uint128 val;
uint128 has;
}
Feed cur;
Feed nxt;
// Whitelisted contracts, set by an auth
mapping (address => uint256) public bud;
modifier toll { require(bud[msg.sender] == 1, "OSM/contract-not-whitelisted"); _; }
event LogValue(bytes32 val);
constructor (address src_) public {
wards[msg.sender] = 1;
src = src_;
}
function stop() external note auth {
stopped = 1;
}
function start() external note auth {
stopped = 0;
}
function change(address src_) external note auth {
src = src_;
}
function era() internal view returns (uint) {
return block.timestamp;
}
function prev(uint ts) internal view returns (uint64) {
require(hop != 0, "OSM/hop-is-zero");
return uint64(ts - (ts % hop));
}
function step(uint16 ts) external auth {
require(ts > 0, "OSM/ts-is-zero");
hop = ts;
}
function void() external note auth {
cur = nxt = Feed(0, 0);
stopped = 1;
}
function pass() public view returns (bool ok) {
return era() >= add(zzz, hop);
}
function poke() external note stoppable {
require(pass(), "OSM/not-passed");
(bytes32 wut, bool ok) = DSValue(src).peek();
if (ok) {
cur = nxt;
nxt = Feed(uint128(uint(wut)), 1);
zzz = prev(era());
emit LogValue(bytes32(uint(cur.val)));
}
}
function peek() external view toll returns (bytes32,bool) {
return (bytes32(uint(cur.val)), cur.has == 1);
}
function peep() external view toll returns (bytes32,bool) {
return (bytes32(uint(nxt.val)), nxt.has == 1);
}
function read() external view toll returns (bytes32) {
require(cur.has == 1, "OSM/no-current-value");
return (bytes32(uint(cur.val)));
}
function kiss(address a) external note auth {
require(a != address(0), "OSM/no-contract-0");
bud[a] = 1;
}
function diss(address a) external note auth {
bud[a] = 0;
}
function kiss(address[] calldata a) external note auth {
for(uint i = 0; i < a.length; i++) {
require(a[i] != address(0), "OSM/no-contract-0");
bud[a[i]] = 1;
}
}
function diss(address[] calldata a) external note auth {
for(uint i = 0; i < a.length; i++) {
bud[a[i]] = 0;
}
}
}File 4 of 12: OSM_STETHUSD
// SPDX-License-Identifier: GNU-3
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.4.23;
interface DSAuthority {
function canCall(
address src, address dst, bytes4 sig
) external view returns (bool);
}
contract DSAuthEvents {
event LogSetAuthority (address indexed authority);
event LogSetOwner (address indexed owner);
}
contract DSAuth is DSAuthEvents {
DSAuthority public authority;
address public owner;
constructor() public {
owner = msg.sender;
emit LogSetOwner(msg.sender);
}
function setOwner(address owner_)
public
auth
{
owner = owner_;
emit LogSetOwner(owner);
}
function setAuthority(DSAuthority authority_)
public
auth
{
authority = authority_;
emit LogSetAuthority(address(authority));
}
modifier auth {
require(isAuthorized(msg.sender, msg.sig), "ds-auth-unauthorized");
_;
}
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
if (src == address(this)) {
return true;
} else if (src == owner) {
return true;
} else if (authority == DSAuthority(address(0))) {
return false;
} else {
return authority.canCall(src, address(this), sig);
}
}
}
/// note.sol -- the `note' modifier, for logging calls as events
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//pragma solidity >=0.4.23;
contract DSNote {
event LogNote(
bytes4 indexed sig,
address indexed guy,
bytes32 indexed foo,
bytes32 indexed bar,
uint256 wad,
bytes fax
) anonymous;
modifier note {
bytes32 foo;
bytes32 bar;
uint256 wad;
assembly {
foo := calldataload(4)
bar := calldataload(36)
wad := callvalue()
}
_;
emit LogNote(msg.sig, msg.sender, foo, bar, wad, msg.data);
}
}
/// math.sol -- mixin for inline numerical wizardry
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//pragma solidity >0.4.13;
contract DSMath {
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x, "ds-math-add-overflow");
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x, "ds-math-sub-underflow");
}
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow");
}
function min(uint x, uint y) internal pure returns (uint z) {
return x <= y ? x : y;
}
function max(uint x, uint y) internal pure returns (uint z) {
return x >= y ? x : y;
}
function imin(int x, int y) internal pure returns (int z) {
return x <= y ? x : y;
}
function imax(int x, int y) internal pure returns (int z) {
return x >= y ? x : y;
}
uint constant WAD = 10 ** 18;
uint constant RAY = 10 ** 27;
//rounds to zero if x*y < WAD / 2
function wmul(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, y), WAD / 2) / WAD;
}
//rounds to zero if x*y < WAD / 2
function rmul(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, y), RAY / 2) / RAY;
}
//rounds to zero if x*y < WAD / 2
function wdiv(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, WAD), y / 2) / y;
}
//rounds to zero if x*y < RAY / 2
function rdiv(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, RAY), y / 2) / y;
}
// This famous algorithm is called "exponentiation by squaring"
// and calculates x^n with x as fixed-point and n as regular unsigned.
//
// It's O(log n), instead of O(n) for naive repeated multiplication.
//
// These facts are why it works:
//
// If n is even, then x^n = (x^2)^(n/2).
// If n is odd, then x^n = x * x^(n-1),
// and applying the equation for even x gives
// x^n = x * (x^2)^((n-1) / 2).
//
// Also, EVM division is flooring and
// floor[(n-1) / 2] = floor[n / 2].
//
function rpow(uint x, uint n) internal pure returns (uint z) {
z = n % 2 != 0 ? x : RAY;
for (n /= 2; n != 0; n /= 2) {
x = rmul(x, x);
if (n % 2 != 0) {
z = rmul(z, x);
}
}
}
}
// thing.sol - `auth` with handy mixins. your things should be DSThings
// Copyright (C) 2017 DappHub, LLC
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//pragma solidity >=0.4.23;
//import 'ds-auth/auth.sol';
//import 'ds-note/note.sol';
//import 'ds-math/math.sol';
contract DSThing is DSAuth, DSNote, DSMath {
function S(string memory s) internal pure returns (bytes4) {
return bytes4(keccak256(abi.encodePacked(s)));
}
}
/// value.sol - a value is a simple thing, it can be get and set
// Copyright (C) 2017 DappHub, LLC
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//pragma solidity >=0.4.23;
//import 'ds-thing/thing.sol';
contract DSValue is DSThing {
bool has;
bytes32 val;
function peek() public view returns (bytes32, bool) {
return (val,has);
}
function read() public view returns (bytes32) {
bytes32 wut; bool haz;
(wut, haz) = peek();
require(haz, "haz-not");
return wut;
}
function poke(bytes32 wut) public note auth {
val = wut;
has = true;
}
function void() public note auth { // unset the value
has = false;
}
}
/// osm.sol
// Copyright (C) 2018-2020 Maker Ecosystem Growth Holdings, INC.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//pragma solidity >=0.5.10;
//import "ds-value/value.sol";
contract LibNote {
event LogNote(
bytes4 indexed sig,
address indexed usr,
bytes32 indexed arg1,
bytes32 indexed arg2,
bytes data
) anonymous;
modifier note {
_;
assembly {
// log an 'anonymous' event with a constant 6 words of calldata
// and four indexed topics: selector, caller, arg1 and arg2
let mark := msize() // end of memory ensures zero
mstore(0x40, add(mark, 288)) // update free memory pointer
mstore(mark, 0x20) // bytes type data offset
mstore(add(mark, 0x20), 224) // bytes size (padded)
calldatacopy(add(mark, 0x40), 0, 224) // bytes payload
log4(mark, 288, // calldata
shl(224, shr(224, calldataload(0))), // msg.sig
caller(), // msg.sender
calldataload(4), // arg1
calldataload(36) // arg2
)
}
}
}
contract OSM_STETHUSD is LibNote {
// --- Auth ---
mapping (address => uint) public wards;
function rely(address usr) external note auth { wards[usr] = 1; }
function deny(address usr) external note auth { wards[usr] = 0; }
modifier auth {
require(wards[msg.sender] == 1, "OSM/not-authorized");
_;
}
// --- Stop ---
uint256 public stopped;
modifier stoppable { require(stopped == 0, "OSM/is-stopped"); _; }
// --- Math ---
function add(uint64 x, uint64 y) internal pure returns (uint64 z) {
z = x + y;
require(z >= x);
}
address public src;
uint16 constant ONE_HOUR = uint16(3600);
uint16 public hop = ONE_HOUR;
uint64 public zzz;
struct Feed {
uint128 val;
uint128 has;
}
Feed cur;
Feed nxt;
// Whitelisted contracts, set by an auth
mapping (address => uint256) public bud;
modifier toll { require(bud[msg.sender] == 1, "OSM/contract-not-whitelisted"); _; }
event LogValue(bytes32 val);
constructor (address src_) public {
wards[msg.sender] = 1;
src = src_;
}
function stop() external note auth {
stopped = 1;
}
function start() external note auth {
stopped = 0;
}
function change(address src_) external note auth {
src = src_;
}
function era() internal view returns (uint) {
return block.timestamp;
}
function prev(uint ts) internal view returns (uint64) {
require(hop != 0, "OSM/hop-is-zero");
return uint64(ts - (ts % hop));
}
function step(uint16 ts) external auth {
require(ts > 0, "OSM/ts-is-zero");
hop = ts;
}
function void() external note auth {
cur = nxt = Feed(0, 0);
stopped = 1;
}
function pass() public view returns (bool ok) {
return era() >= add(zzz, hop);
}
function poke() external note stoppable {
require(pass(), "OSM/not-passed");
(bytes32 wut, bool ok) = DSValue(src).peek();
if (ok) {
cur = nxt;
nxt = Feed(uint128(uint(wut)), 1);
zzz = prev(era());
emit LogValue(bytes32(uint(cur.val)));
}
}
function peek() external view toll returns (bytes32,bool) {
return (bytes32(uint(cur.val)), cur.has == 1);
}
function peep() external view toll returns (bytes32,bool) {
return (bytes32(uint(nxt.val)), nxt.has == 1);
}
function read() external view toll returns (bytes32) {
require(cur.has == 1, "OSM/no-current-value");
return (bytes32(uint(cur.val)));
}
function kiss(address a) external note auth {
require(a != address(0), "OSM/no-contract-0");
bud[a] = 1;
}
function diss(address a) external note auth {
bud[a] = 0;
}
function kiss(address[] calldata a) external note auth {
for(uint i = 0; i < a.length; i++) {
require(a[i] != address(0), "OSM/no-contract-0");
bud[a[i]] = 1;
}
}
function diss(address[] calldata a) external note auth {
for(uint i = 0; i < a.length; i++) {
bud[a[i]] = 0;
}
}
}File 5 of 12: OSM
/**
*Submitted for verification at Etherscan.io on 2019-11-13
*/
// osm.sol - Oracle Security Module
// Copyright (C) 2019 Maker Foundation
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
contract DSAuthority {
function canCall(
address src, address dst, bytes4 sig
) public view returns (bool);
}
contract DSAuthEvents {
event LogSetAuthority (address indexed authority);
event LogSetOwner (address indexed owner);
}
contract DSAuth is DSAuthEvents {
DSAuthority public authority;
address public owner;
constructor() public {
owner = msg.sender;
emit LogSetOwner(msg.sender);
}
function setOwner(address owner_)
public
auth
{
owner = owner_;
emit LogSetOwner(owner);
}
function setAuthority(DSAuthority authority_)
public
auth
{
authority = authority_;
emit LogSetAuthority(address(authority));
}
modifier auth {
require(isAuthorized(msg.sender, msg.sig), "ds-auth-unauthorized");
_;
}
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
if (src == address(this)) {
return true;
} else if (src == owner) {
return true;
} else if (authority == DSAuthority(0)) {
return false;
} else {
return authority.canCall(src, address(this), sig);
}
}
}
////// lib/ds-stop/lib/ds-note/src/note.sol
/// note.sol -- the `note' modifier, for logging calls as events
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/* pragma solidity >=0.4.23; */
contract DSNote {
event LogNote(
bytes4 indexed sig,
address indexed guy,
bytes32 indexed foo,
bytes32 indexed bar,
uint256 wad,
bytes fax
) anonymous;
modifier note {
bytes32 foo;
bytes32 bar;
uint256 wad;
assembly {
foo := calldataload(4)
bar := calldataload(36)
wad := callvalue
}
emit LogNote(msg.sig, msg.sender, foo, bar, wad, msg.data);
_;
}
}
////// lib/ds-value/lib/ds-thing/lib/ds-math/src/math.sol
/// math.sol -- mixin for inline numerical wizardry
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/* pragma solidity >0.4.13; */
contract DSMath {
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x, "ds-math-add-overflow");
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x, "ds-math-sub-underflow");
}
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow");
}
function min(uint x, uint y) internal pure returns (uint z) {
return x <= y ? x : y;
}
function max(uint x, uint y) internal pure returns (uint z) {
return x >= y ? x : y;
}
function imin(int x, int y) internal pure returns (int z) {
return x <= y ? x : y;
}
function imax(int x, int y) internal pure returns (int z) {
return x >= y ? x : y;
}
uint constant WAD = 10 ** 18;
uint constant RAY = 10 ** 27;
function wmul(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, y), WAD / 2) / WAD;
}
function rmul(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, y), RAY / 2) / RAY;
}
function wdiv(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, WAD), y / 2) / y;
}
function rdiv(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, RAY), y / 2) / y;
}
// This famous algorithm is called "exponentiation by squaring"
// and calculates x^n with x as fixed-point and n as regular unsigned.
//
// It's O(log n), instead of O(n) for naive repeated multiplication.
//
// These facts are why it works:
//
// If n is even, then x^n = (x^2)^(n/2).
// If n is odd, then x^n = x * x^(n-1),
// and applying the equation for even x gives
// x^n = x * (x^2)^((n-1) / 2).
//
// Also, EVM division is flooring and
// floor[(n-1) / 2] = floor[n / 2].
//
function rpow(uint x, uint n) internal pure returns (uint z) {
z = n % 2 != 0 ? x : RAY;
for (n /= 2; n != 0; n /= 2) {
x = rmul(x, x);
if (n % 2 != 0) {
z = rmul(z, x);
}
}
}
}
////// lib/ds-value/lib/ds-thing/src/thing.sol
// thing.sol - `auth` with handy mixins. your things should be DSThings
// Copyright (C) 2017 DappHub, LLC
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/* pragma solidity >=0.4.23; */
/* import 'ds-auth/auth.sol'; */
/* import 'ds-note/note.sol'; */
/* import 'ds-math/math.sol'; */
contract DSThing is DSAuth, DSNote, DSMath {
function S(string memory s) internal pure returns (bytes4) {
return bytes4(keccak256(abi.encodePacked(s)));
}
}
////// lib/ds-value/src/value.sol
/// value.sol - a value is a simple thing, it can be get and set
// Copyright (C) 2017 DappHub, LLC
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/* pragma solidity >=0.4.23; */
/* import 'ds-thing/thing.sol'; */
contract DSValue is DSThing {
bool has;
bytes32 val;
function peek() public view returns (bytes32, bool) {
return (val,has);
}
function read() public view returns (bytes32) {
bytes32 wut; bool haz;
(wut, haz) = peek();
require(haz, "haz-not");
return wut;
}
function poke(bytes32 wut) public note auth {
val = wut;
has = true;
}
function void() public note auth { // unset the value
has = false;
}
}
////// src/osm.sol
/* pragma solidity >=0.5.10; */
/* import "ds-value/value.sol"; */
contract LibNote {
event LogNote(
bytes4 indexed sig,
address indexed usr,
bytes32 indexed arg1,
bytes32 indexed arg2,
bytes data
) anonymous;
modifier note {
_;
assembly {
// log an 'anonymous' event with a constant 6 words of calldata
// and four indexed topics: selector, caller, arg1 and arg2
let mark := msize // end of memory ensures zero
mstore(0x40, add(mark, 288)) // update free memory pointer
mstore(mark, 0x20) // bytes type data offset
mstore(add(mark, 0x20), 224) // bytes size (padded)
calldatacopy(add(mark, 0x40), 0, 224) // bytes payload
log4(mark, 288, // calldata
shl(224, shr(224, calldataload(0))), // msg.sig
caller, // msg.sender
calldataload(4), // arg1
calldataload(36) // arg2
)
}
}
}
contract OSM is LibNote {
// --- Auth ---
mapping (address => uint) public wards;
function rely(address usr) external note auth { wards[usr] = 1; }
function deny(address usr) external note auth { wards[usr] = 0; }
modifier auth {
require(wards[msg.sender] == 1, "OSM/not-authorized");
_;
}
// --- Stop ---
uint256 public stopped;
modifier stoppable { require(stopped == 0, "OSM/is-stopped"); _; }
// --- Math ---
function add(uint64 x, uint64 y) internal pure returns (uint64 z) {
z = x + y;
require(z >= x);
}
address public src;
uint16 constant ONE_HOUR = uint16(3600);
uint16 public hop = ONE_HOUR;
uint64 public zzz;
struct Feed {
uint128 val;
uint128 has;
}
Feed cur;
Feed nxt;
// Whitelisted contracts, set by an auth
mapping (address => uint256) public bud;
modifier toll { require(bud[msg.sender] == 1, "OSM/contract-not-whitelisted"); _; }
event LogValue(bytes32 val);
constructor (address src_) public {
wards[msg.sender] = 1;
src = src_;
}
function stop() external note auth {
stopped = 1;
}
function start() external note auth {
stopped = 0;
}
function change(address src_) external note auth {
src = src_;
}
function era() internal view returns (uint) {
return block.timestamp;
}
function prev(uint ts) internal view returns (uint64) {
require(hop != 0, "OSM/hop-is-zero");
return uint64(ts - (ts % hop));
}
function step(uint16 ts) external auth {
require(ts > 0, "OSM/ts-is-zero");
hop = ts;
}
function void() external note auth {
cur = nxt = Feed(0, 0);
stopped = 1;
}
function pass() public view returns (bool ok) {
return era() >= add(zzz, hop);
}
function poke() external note stoppable {
require(pass(), "OSM/not-passed");
(bytes32 wut, bool ok) = DSValue(src).peek();
if (ok) {
cur = nxt;
nxt = Feed(uint128(uint(wut)), 1);
zzz = prev(era());
emit LogValue(bytes32(uint(cur.val)));
}
}
function peek() external view toll returns (bytes32,bool) {
return (bytes32(uint(cur.val)), cur.has == 1);
}
function peep() external view toll returns (bytes32,bool) {
return (bytes32(uint(nxt.val)), nxt.has == 1);
}
function read() external view toll returns (bytes32) {
require(cur.has == 1, "OSM/no-current-value");
return (bytes32(uint(cur.val)));
}
function kiss(address a) external note auth {
require(a != address(0), "OSM/no-contract-0");
bud[a] = 1;
}
function diss(address a) external note auth {
bud[a] = 0;
}
function kiss(address[] calldata a) external note auth {
for(uint i = 0; i < a.length; i++) {
require(a[i] != address(0), "OSM/no-contract-0");
bud[a[i]] = 1;
}
}
function diss(address[] calldata a) external note auth {
for(uint i = 0; i < a.length; i++) {
bud[a[i]] = 0;
}
}
}File 6 of 12: Sequencer
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2021 Dai Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pragma solidity 0.8.13;
import "./utils/EnumerableSet.sol";
interface JobLike {
function workable(bytes32 network) external returns (bool canWork, bytes memory args);
}
/// @title Coordination between Keeper Networks
/// @dev Only one should be active at a time
///
/// Use the block number to switch between networks
contract Sequencer {
using EnumerableSet for EnumerableSet.AddressSet;
using EnumerableSet for EnumerableSet.Bytes32Set;
struct Window {
uint256 start;
uint256 length;
}
struct WorkableJob {
address job;
bool canWork;
bytes args;
}
// --- Auth ---
mapping (address => uint256) public wards;
function rely(address usr) external auth {
wards[usr] = 1;
emit Rely(usr);
}
function deny(address usr) external auth {
wards[usr] = 0;
emit Deny(usr);
}
modifier auth {
require(wards[msg.sender] == 1, "Sequencer/not-authorized");
_;
}
EnumerableSet.Bytes32Set private networks;
EnumerableSet.AddressSet private jobs;
mapping(bytes32 => Window) public windows;
uint256 public totalWindowSize;
// --- Events ---
event Rely(address indexed usr);
event Deny(address indexed usr);
event AddNetwork(bytes32 indexed network, uint256 windowSize);
event RemoveNetwork(bytes32 indexed network);
event AddJob(address indexed job);
event RemoveJob(address indexed job);
// --- Errors ---
error WindowZero(bytes32 network);
error NetworkExists(bytes32 network);
error NetworkDoesNotExist(bytes32 network);
error JobExists(address job);
error JobDoesNotExist(address network);
error IndexTooHigh(uint256 index, uint256 length);
error BadIndicies(uint256 startIndex, uint256 exclEndIndex);
constructor() {
wards[msg.sender] = 1;
emit Rely(msg.sender);
}
// --- Network Admin ---
function refreshStarts() internal {
uint256 start = 0;
uint256 netLen = networks.length();
for (uint256 i = 0; i < netLen; i++) {
bytes32 network = networks.at(i);
windows[network].start = start;
start += windows[network].length;
}
}
function addNetwork(bytes32 network, uint256 windowSize) external auth {
if (!networks.add(network)) revert NetworkExists(network);
if (windowSize == 0) revert WindowZero(network);
windows[network] = Window({
start: 0, // start will be set in refreshStarts
length: windowSize
});
totalWindowSize += windowSize;
refreshStarts();
emit AddNetwork(network, windowSize);
}
function removeNetwork(bytes32 network) external auth {
if (!networks.remove(network)) revert NetworkDoesNotExist(network);
uint256 windowSize = windows[network].length;
delete windows[network];
totalWindowSize -= windowSize;
refreshStarts();
emit RemoveNetwork(network);
}
// --- Job Admin ---
function addJob(address job) external auth {
if (!jobs.add(job)) revert JobExists(job);
emit AddJob(job);
}
function removeJob(address job) external auth {
if (!jobs.remove(job)) revert JobDoesNotExist(job);
emit RemoveJob(job);
}
// --- Views ---
function isMaster(bytes32 network) external view returns (bool) {
if (networks.length() == 0) return false;
Window memory window = windows[network];
uint256 pos = block.number % totalWindowSize;
return window.start <= pos && pos < window.start + window.length;
}
function getMaster() external view returns (bytes32) {
uint256 netLen = networks.length();
if (netLen == 0) return bytes32(0);
uint256 pos = block.number % totalWindowSize;
for (uint256 i = 0; i < netLen; i++) {
bytes32 network = networks.at(i);
Window memory window = windows[network];
if (window.start <= pos && pos < window.start + window.length) {
return network;
}
}
return bytes32(0);
}
function numNetworks() external view returns (uint256) {
return networks.length();
}
function hasNetwork(bytes32 network) public view returns (bool) {
return networks.contains(network);
}
function networkAt(uint256 index) public view returns (bytes32) {
return networks.at(index);
}
function numJobs() external view returns (uint256) {
return jobs.length();
}
function hasJob(address job) public view returns (bool) {
return jobs.contains(job);
}
function jobAt(uint256 index) public view returns (address) {
return jobs.at(index);
}
// --- Job helper functions ---
function getNextJobs(bytes32 network, uint256 startIndex, uint256 endIndexExcl) public returns (WorkableJob[] memory) {
if (endIndexExcl < startIndex) revert BadIndicies(startIndex, endIndexExcl);
uint256 length = jobs.length();
if (endIndexExcl > length) revert IndexTooHigh(endIndexExcl, length);
WorkableJob[] memory _jobs = new WorkableJob[](endIndexExcl - startIndex);
for (uint256 i = startIndex; i < endIndexExcl; i++) {
JobLike job = JobLike(jobs.at(i));
(bool canWork, bytes memory args) = job.workable(network);
_jobs[i - startIndex] = WorkableJob(address(job), canWork, args);
}
return _jobs;
}
function getNextJobs(bytes32 network) external returns (WorkableJob[] memory) {
return getNextJobs(network, 0, jobs.length());
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol)
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
return _values(set._inner);
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}
File 7 of 12: Vat
// hevm: flattened sources of /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/vat.sol
pragma solidity =0.5.12;
////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/vat.sol
/// vat.sol -- Dai CDP database
// Copyright (C) 2018 Rain <rainbreak@riseup.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
/* pragma solidity 0.5.12; */
contract Vat {
// --- Auth ---
mapping (address => uint) public wards;
function rely(address usr) external note auth { require(live == 1, "Vat/not-live"); wards[usr] = 1; }
function deny(address usr) external note auth { require(live == 1, "Vat/not-live"); wards[usr] = 0; }
modifier auth {
require(wards[msg.sender] == 1, "Vat/not-authorized");
_;
}
mapping(address => mapping (address => uint)) public can;
function hope(address usr) external note { can[msg.sender][usr] = 1; }
function nope(address usr) external note { can[msg.sender][usr] = 0; }
function wish(address bit, address usr) internal view returns (bool) {
return either(bit == usr, can[bit][usr] == 1);
}
// --- Data ---
struct Ilk {
uint256 Art; // Total Normalised Debt [wad]
uint256 rate; // Accumulated Rates [ray]
uint256 spot; // Price with Safety Margin [ray]
uint256 line; // Debt Ceiling [rad]
uint256 dust; // Urn Debt Floor [rad]
}
struct Urn {
uint256 ink; // Locked Collateral [wad]
uint256 art; // Normalised Debt [wad]
}
mapping (bytes32 => Ilk) public ilks;
mapping (bytes32 => mapping (address => Urn )) public urns;
mapping (bytes32 => mapping (address => uint)) public gem; // [wad]
mapping (address => uint256) public dai; // [rad]
mapping (address => uint256) public sin; // [rad]
uint256 public debt; // Total Dai Issued [rad]
uint256 public vice; // Total Unbacked Dai [rad]
uint256 public Line; // Total Debt Ceiling [rad]
uint256 public live; // Access Flag
// --- Logs ---
event LogNote(
bytes4 indexed sig,
bytes32 indexed arg1,
bytes32 indexed arg2,
bytes32 indexed arg3,
bytes data
) anonymous;
modifier note {
_;
assembly {
// log an 'anonymous' event with a constant 6 words of calldata
// and four indexed topics: the selector and the first three args
let mark := msize // end of memory ensures zero
mstore(0x40, add(mark, 288)) // update free memory pointer
mstore(mark, 0x20) // bytes type data offset
mstore(add(mark, 0x20), 224) // bytes size (padded)
calldatacopy(add(mark, 0x40), 0, 224) // bytes payload
log4(mark, 288, // calldata
shl(224, shr(224, calldataload(0))), // msg.sig
calldataload(4), // arg1
calldataload(36), // arg2
calldataload(68) // arg3
)
}
}
// --- Init ---
constructor() public {
wards[msg.sender] = 1;
live = 1;
}
// --- Math ---
function add(uint x, int y) internal pure returns (uint z) {
z = x + uint(y);
require(y >= 0 || z <= x);
require(y <= 0 || z >= x);
}
function sub(uint x, int y) internal pure returns (uint z) {
z = x - uint(y);
require(y <= 0 || z <= x);
require(y >= 0 || z >= x);
}
function mul(uint x, int y) internal pure returns (int z) {
z = int(x) * y;
require(int(x) >= 0);
require(y == 0 || z / y == int(x));
}
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x);
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x);
}
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x);
}
// --- Administration ---
function init(bytes32 ilk) external note auth {
require(ilks[ilk].rate == 0, "Vat/ilk-already-init");
ilks[ilk].rate = 10 ** 27;
}
function file(bytes32 what, uint data) external note auth {
require(live == 1, "Vat/not-live");
if (what == "Line") Line = data;
else revert("Vat/file-unrecognized-param");
}
function file(bytes32 ilk, bytes32 what, uint data) external note auth {
require(live == 1, "Vat/not-live");
if (what == "spot") ilks[ilk].spot = data;
else if (what == "line") ilks[ilk].line = data;
else if (what == "dust") ilks[ilk].dust = data;
else revert("Vat/file-unrecognized-param");
}
function cage() external note auth {
live = 0;
}
// --- Fungibility ---
function slip(bytes32 ilk, address usr, int256 wad) external note auth {
gem[ilk][usr] = add(gem[ilk][usr], wad);
}
function flux(bytes32 ilk, address src, address dst, uint256 wad) external note {
require(wish(src, msg.sender), "Vat/not-allowed");
gem[ilk][src] = sub(gem[ilk][src], wad);
gem[ilk][dst] = add(gem[ilk][dst], wad);
}
function move(address src, address dst, uint256 rad) external note {
require(wish(src, msg.sender), "Vat/not-allowed");
dai[src] = sub(dai[src], rad);
dai[dst] = add(dai[dst], rad);
}
function either(bool x, bool y) internal pure returns (bool z) {
assembly{ z := or(x, y)}
}
function both(bool x, bool y) internal pure returns (bool z) {
assembly{ z := and(x, y)}
}
// --- CDP Manipulation ---
function frob(bytes32 i, address u, address v, address w, int dink, int dart) external note {
// system is live
require(live == 1, "Vat/not-live");
Urn memory urn = urns[i][u];
Ilk memory ilk = ilks[i];
// ilk has been initialised
require(ilk.rate != 0, "Vat/ilk-not-init");
urn.ink = add(urn.ink, dink);
urn.art = add(urn.art, dart);
ilk.Art = add(ilk.Art, dart);
int dtab = mul(ilk.rate, dart);
uint tab = mul(ilk.rate, urn.art);
debt = add(debt, dtab);
// either debt has decreased, or debt ceilings are not exceeded
require(either(dart <= 0, both(mul(ilk.Art, ilk.rate) <= ilk.line, debt <= Line)), "Vat/ceiling-exceeded");
// urn is either less risky than before, or it is safe
require(either(both(dart <= 0, dink >= 0), tab <= mul(urn.ink, ilk.spot)), "Vat/not-safe");
// urn is either more safe, or the owner consents
require(either(both(dart <= 0, dink >= 0), wish(u, msg.sender)), "Vat/not-allowed-u");
// collateral src consents
require(either(dink <= 0, wish(v, msg.sender)), "Vat/not-allowed-v");
// debt dst consents
require(either(dart >= 0, wish(w, msg.sender)), "Vat/not-allowed-w");
// urn has no debt, or a non-dusty amount
require(either(urn.art == 0, tab >= ilk.dust), "Vat/dust");
gem[i][v] = sub(gem[i][v], dink);
dai[w] = add(dai[w], dtab);
urns[i][u] = urn;
ilks[i] = ilk;
}
// --- CDP Fungibility ---
function fork(bytes32 ilk, address src, address dst, int dink, int dart) external note {
Urn storage u = urns[ilk][src];
Urn storage v = urns[ilk][dst];
Ilk storage i = ilks[ilk];
u.ink = sub(u.ink, dink);
u.art = sub(u.art, dart);
v.ink = add(v.ink, dink);
v.art = add(v.art, dart);
uint utab = mul(u.art, i.rate);
uint vtab = mul(v.art, i.rate);
// both sides consent
require(both(wish(src, msg.sender), wish(dst, msg.sender)), "Vat/not-allowed");
// both sides safe
require(utab <= mul(u.ink, i.spot), "Vat/not-safe-src");
require(vtab <= mul(v.ink, i.spot), "Vat/not-safe-dst");
// both sides non-dusty
require(either(utab >= i.dust, u.art == 0), "Vat/dust-src");
require(either(vtab >= i.dust, v.art == 0), "Vat/dust-dst");
}
// --- CDP Confiscation ---
function grab(bytes32 i, address u, address v, address w, int dink, int dart) external note auth {
Urn storage urn = urns[i][u];
Ilk storage ilk = ilks[i];
urn.ink = add(urn.ink, dink);
urn.art = add(urn.art, dart);
ilk.Art = add(ilk.Art, dart);
int dtab = mul(ilk.rate, dart);
gem[i][v] = sub(gem[i][v], dink);
sin[w] = sub(sin[w], dtab);
vice = sub(vice, dtab);
}
// --- Settlement ---
function heal(uint rad) external note {
address u = msg.sender;
sin[u] = sub(sin[u], rad);
dai[u] = sub(dai[u], rad);
vice = sub(vice, rad);
debt = sub(debt, rad);
}
function suck(address u, address v, uint rad) external note auth {
sin[u] = add(sin[u], rad);
dai[v] = add(dai[v], rad);
vice = add(vice, rad);
debt = add(debt, rad);
}
// --- Rates ---
function fold(bytes32 i, address u, int rate) external note auth {
require(live == 1, "Vat/not-live");
Ilk storage ilk = ilks[i];
ilk.rate = add(ilk.rate, rate);
int rad = mul(ilk.Art, rate);
dai[u] = add(dai[u], rad);
debt = add(debt, rad);
}
}File 8 of 12: IlkRegistry
// SPDX-License-Identifier: AGPL-3.0-or-later
/// IlkRegistry.sol -- Publicly updatable ilk registry
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pragma solidity ^0.6.12;
interface JoinLike {
function vat() external view returns (address);
function ilk() external view returns (bytes32);
function gem() external view returns (address);
function dec() external view returns (uint256);
function live() external view returns (uint256);
}
interface VatLike {
function wards(address) external view returns (uint256);
function live() external view returns (uint256);
}
interface DogLike {
function vat() external view returns (address);
function live() external view returns (uint256);
function ilks(bytes32) external view returns (address, uint256, uint256, uint256);
}
interface CatLike {
function vat() external view returns (address);
function live() external view returns (uint256);
function ilks(bytes32) external view returns (address, uint256, uint256);
}
interface FlipLike {
function vat() external view returns (address);
function cat() external view returns (address);
}
interface ClipLike {
function vat() external view returns (address);
function dog() external view returns (address);
}
interface SpotLike {
function live() external view returns (uint256);
function vat() external view returns (address);
function ilks(bytes32) external view returns (address, uint256);
}
interface TokenLike {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
}
contract GemInfo {
function name(address token) external view returns (string memory) {
return TokenLike(token).name();
}
function symbol(address token) external view returns (string memory) {
return TokenLike(token).symbol();
}
}
contract IlkRegistry {
event Rely(address usr);
event Deny(address usr);
event File(bytes32 what, address data);
event File(bytes32 ilk, bytes32 what, address data);
event File(bytes32 ilk, bytes32 what, uint256 data);
event File(bytes32 ilk, bytes32 what, string data);
event AddIlk(bytes32 ilk);
event RemoveIlk(bytes32 ilk);
event UpdateIlk(bytes32 ilk);
event NameError(bytes32 ilk);
event SymbolError(bytes32 ilk);
// --- Auth ---
mapping (address => uint) public wards;
function rely(address usr) external auth { wards[usr] = 1; emit Rely(usr); }
function deny(address usr) external auth { wards[usr] = 0; emit Deny(usr); }
modifier auth {
require(wards[msg.sender] == 1, "IlkRegistry/not-authorized");
_;
}
VatLike public immutable vat;
GemInfo private immutable gemInfo;
DogLike public dog;
CatLike public cat;
SpotLike public spot;
struct Ilk {
uint96 pos; // Index in ilks array
address join; // DSS GemJoin adapter
address gem; // The token contract
uint8 dec; // Token decimals
uint96 class; // Classification code (1 - clip, 2 - flip, 3+ - other)
address pip; // Token price
address xlip; // Auction contract
string name; // Token name
string symbol; // Token symbol
}
mapping (bytes32 => Ilk) public ilkData;
bytes32[] ilks;
// Initialize the registry
constructor(address vat_, address dog_, address cat_, address spot_) public {
VatLike _vat = vat = VatLike(vat_);
dog = DogLike(dog_);
cat = CatLike(cat_);
spot = SpotLike(spot_);
require(dog.vat() == vat_, "IlkRegistry/invalid-dog-vat");
require(cat.vat() == vat_, "IlkRegistry/invalid-cat-vat");
require(spot.vat() == vat_, "IlkRegistry/invalid-spotter-vat");
require(_vat.wards(cat_) == 1, "IlkRegistry/cat-not-authorized");
require(_vat.wards(spot_) == 1, "IlkRegistry/spot-not-authorized");
require(_vat.live() == 1, "IlkRegistry/vat-not-live");
require(cat.live() == 1, "IlkRegistry/cat-not-live");
require(spot.live() == 1, "IlkRegistry/spot-not-live");
gemInfo = new GemInfo();
wards[msg.sender] = 1;
}
// Pass an active join adapter to the registry to add it to the set
function add(address adapter) external {
JoinLike _join = JoinLike(adapter);
// Validate adapter
require(_join.vat() == address(vat), "IlkRegistry/invalid-join-adapter-vat");
require(vat.wards(address(_join)) == 1, "IlkRegistry/adapter-not-authorized");
// Validate ilk
bytes32 _ilk = _join.ilk();
require(_ilk != 0, "IlkRegistry/ilk-adapter-invalid");
require(ilkData[_ilk].join == address(0), "IlkRegistry/ilk-already-exists");
(address _pip,) = spot.ilks(_ilk);
require(_pip != address(0), "IlkRegistry/pip-invalid");
(address _xlip,,,) = dog.ilks(_ilk);
uint96 _class = 1;
if (_xlip == address(0)) {
(_xlip,,) = cat.ilks(_ilk);
require(_xlip != address(0), "IlkRegistry/invalid-auction-contract");
_class = 2;
}
string memory name = bytes32ToStr(_ilk);
try gemInfo.name(_join.gem()) returns (string memory _name) {
if (bytes(_name).length != 0) {
name = _name;
}
} catch {
emit NameError(_ilk);
}
string memory symbol = bytes32ToStr(_ilk);
try gemInfo.symbol(_join.gem()) returns (string memory _symbol) {
if (bytes(_symbol).length != 0) {
symbol = _symbol;
}
} catch {
emit SymbolError(_ilk);
}
require(ilks.length < uint96(-1), "IlkRegistry/too-many-ilks");
ilks.push(_ilk);
ilkData[ilks[ilks.length - 1]] = Ilk({
pos: uint96(ilks.length - 1),
join: address(_join),
gem: _join.gem(),
dec: uint8(_join.dec()),
class: _class,
pip: _pip,
xlip: _xlip,
name: name,
symbol: symbol
});
emit AddIlk(_ilk);
}
// Anyone can remove an ilk if the adapter has been caged
function remove(bytes32 ilk) external {
JoinLike _join = JoinLike(ilkData[ilk].join);
require(address(_join) != address(0), "IlkRegistry/invalid-ilk");
uint96 _class = ilkData[ilk].class;
require(_class == 1 || _class == 2, "IlkRegistry/invalid-class");
require(_join.live() == 0, "IlkRegistry/ilk-live");
_remove(ilk);
emit RemoveIlk(ilk);
}
// Admin can remove an ilk without any precheck
function removeAuth(bytes32 ilk) external auth {
_remove(ilk);
emit RemoveIlk(ilk);
}
// Authed edit function
function file(bytes32 what, address data) external auth {
if (what == "dog") dog = DogLike(data);
else if (what == "cat") cat = CatLike(data);
else if (what == "spot") spot = SpotLike(data);
else revert("IlkRegistry/file-unrecognized-param-address");
emit File(what, data);
}
// Authed edit function
function file(bytes32 ilk, bytes32 what, address data) external auth {
if (what == "gem") ilkData[ilk].gem = data;
else if (what == "join") ilkData[ilk].join = data;
else if (what == "pip") ilkData[ilk].pip = data;
else if (what == "xlip") ilkData[ilk].xlip = data;
else revert("IlkRegistry/file-unrecognized-param-address");
emit File(ilk, what, data);
}
// Authed edit function
function file(bytes32 ilk, bytes32 what, uint256 data) external auth {
if (what == "class") { require(data <= uint96(-1) && data != 0); ilkData[ilk].class = uint96(data); }
else if (what == "dec") { require(data <= uint8(-1)); ilkData[ilk].dec = uint8(data); }
else revert("IlkRegistry/file-unrecognized-param-uint256");
emit File(ilk, what, data);
}
// Authed edit function
function file(bytes32 ilk, bytes32 what, string calldata data) external auth {
if (what == "name") ilkData[ilk].name = data;
else if (what == "symbol") ilkData[ilk].symbol = data;
else revert("IlkRegistry/file-unrecognized-param-string");
emit File(ilk, what, data);
}
// Remove ilk from the ilks array by replacing the ilk with the
// last in the array and then trimming the end.
function _remove(bytes32 ilk) internal {
// Get the position in the array
uint256 _index = ilkData[ilk].pos;
// Get the last ilk in the array
bytes32 _moveIlk = ilks[ilks.length - 1];
// Replace the ilk we are removing
ilks[_index] = _moveIlk;
// Update the array position for the moved ilk
ilkData[_moveIlk].pos = uint96(_index);
// Trim off the end of the ilks array
ilks.pop();
// Delete struct data
delete ilkData[ilk];
}
// The number of active ilks
function count() external view returns (uint256) {
return ilks.length;
}
// Return an array of the available ilks
function list() external view returns (bytes32[] memory) {
return ilks;
}
// Get a splice of the available ilks, useful when ilks array is large.
function list(uint256 start, uint256 end) external view returns (bytes32[] memory) {
require(start <= end && end < ilks.length, "IlkRegistry/invalid-input");
bytes32[] memory _ilks = new bytes32[]((end - start) + 1);
uint256 _count = 0;
for (uint256 i = start; i <= end; i++) {
_ilks[_count] = ilks[i];
_count++;
}
return _ilks;
}
// Get the ilk at a specific position in the array
function get(uint256 pos) external view returns (bytes32) {
require(pos < ilks.length, "IlkRegistry/index-out-of-range");
return ilks[pos];
}
// Get information about an ilk, including name and symbol
function info(bytes32 ilk) external view returns (
string memory name,
string memory symbol,
uint256 class,
uint256 dec,
address gem,
address pip,
address join,
address xlip
) {
Ilk memory _ilk = ilkData[ilk];
return (
_ilk.name,
_ilk.symbol,
_ilk.class,
_ilk.dec,
_ilk.gem,
_ilk.pip,
_ilk.join,
_ilk.xlip
);
}
// The location of the ilk in the ilks array
function pos(bytes32 ilk) external view returns (uint256) {
return ilkData[ilk].pos;
}
// The classification code of the ilk
// 1 - Flipper
// 2 - Clipper
// 3+ - RWA or custom adapter
function class(bytes32 ilk) external view returns (uint256) {
return ilkData[ilk].class;
}
// The token address
function gem(bytes32 ilk) external view returns (address) {
return ilkData[ilk].gem;
}
// The ilk's price feed
function pip(bytes32 ilk) external view returns (address) {
return ilkData[ilk].pip;
}
// The ilk's join adapter
function join(bytes32 ilk) external view returns (address) {
return ilkData[ilk].join;
}
// The auction contract for the ilk
function xlip(bytes32 ilk) external view returns (address) {
return ilkData[ilk].xlip;
}
// The number of decimals on the ilk
function dec(bytes32 ilk) external view returns (uint256) {
return ilkData[ilk].dec;
}
// Return the symbol of the token, if available
function symbol(bytes32 ilk) external view returns (string memory) {
return ilkData[ilk].symbol;
}
// Return the name of the token, if available
function name(bytes32 ilk) external view returns (string memory) {
return ilkData[ilk].name;
}
// Public function to update an ilk's pip and flip if the ilk has been updated.
function update(bytes32 ilk) external {
require(JoinLike(ilkData[ilk].join).vat() == address(vat), "IlkRegistry/invalid-ilk");
require(JoinLike(ilkData[ilk].join).live() == 1, "IlkRegistry/ilk-not-live-use-remove-instead");
uint96 _class = ilkData[ilk].class;
require(_class == 1 || _class == 2, "IlkRegistry/invalid-class");
(address _pip,) = spot.ilks(ilk);
require(_pip != address(0), "IlkRegistry/pip-invalid");
ilkData[ilk].pip = _pip;
emit UpdateIlk(ilk);
}
// Force addition or update of a collateral type. (i.e. for RWA, etc.)
// Governance managed
function put(
bytes32 _ilk,
address _join,
address _gem,
uint256 _dec,
uint256 _class,
address _pip,
address _xlip,
string calldata _name,
string calldata _symbol
)
external auth {
require(_class != 0 && _class <= uint96(-1), "IlkRegistry/invalid-class");
require(_dec <= uint8(-1), "IlkRegistry/invalid-dec");
uint96 _pos;
if (ilkData[_ilk].class == 0) {
require(ilks.length < uint96(-1), "IlkRegistry/too-many-ilks");
ilks.push(_ilk);
_pos = uint96(ilks.length - 1);
emit AddIlk(_ilk);
} else {
_pos = ilkData[_ilk].pos;
emit UpdateIlk(_ilk);
}
ilkData[ilks[_pos]] = Ilk({
pos: _pos,
join: _join,
gem: _gem,
dec: uint8(_dec),
class: uint96(_class),
pip: _pip,
xlip: _xlip,
name: _name,
symbol: _symbol
});
}
function bytes32ToStr(bytes32 _bytes32) internal pure returns (string memory) {
bytes memory _bytesArray = new bytes(32);
for (uint256 i; i < 32; i++) {
_bytesArray[i] = _bytes32[i];
}
return string(_bytesArray);
}
}File 9 of 12: MedianETHUSD
// median.sol - Medianizer v2
// Copyright (C) 2019 Maker Foundation
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.5.10;
contract LibNote {
event LogNote(
bytes4 indexed sig,
address indexed usr,
bytes32 indexed arg1,
bytes32 indexed arg2,
bytes data
) anonymous;
modifier note {
_;
assembly {
// log an 'anonymous' event with a constant 6 words of calldata
// and four indexed topics: selector, caller, arg1 and arg2
let mark := msize // end of memory ensures zero
mstore(0x40, add(mark, 288)) // update free memory pointer
mstore(mark, 0x20) // bytes type data offset
mstore(add(mark, 0x20), 224) // bytes size (padded)
calldatacopy(add(mark, 0x40), 0, 224) // bytes payload
log4(mark, 288, // calldata
shl(224, shr(224, calldataload(0))), // msg.sig
caller, // msg.sender
calldataload(4), // arg1
calldataload(36) // arg2
)
}
}
}
contract Median is LibNote {
// --- Auth ---
mapping (address => uint) public wards;
function rely(address usr) external note auth { wards[usr] = 1; }
function deny(address usr) external note auth { wards[usr] = 0; }
modifier auth {
require(wards[msg.sender] == 1, "Median/not-authorized");
_;
}
uint128 val;
uint32 public age;
bytes32 public constant wat = "ethusd"; // You want to change this every deploy
uint256 public bar = 1;
// Authorized oracles, set by an auth
mapping (address => uint256) public orcl;
// Whitelisted contracts, set by an auth
mapping (address => uint256) public bud;
// Mapping for at most 256 oracles
mapping (uint8 => address) public slot;
modifier toll { require(bud[msg.sender] == 1, "Median/contract-not-whitelisted"); _;}
event LogMedianPrice(uint256 val, uint256 age);
//Set type of Oracle
constructor() public {
wards[msg.sender] = 1;
}
function read() external view toll returns (uint256) {
require(val > 0, "Median/invalid-price-feed");
return val;
}
function peek() external view toll returns (uint256,bool) {
return (val, val > 0);
}
function recover(uint256 val_, uint256 age_, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
return ecrecover(
keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(abi.encodePacked(val_, age_, wat)))),
v, r, s
);
}
function poke(
uint256[] calldata val_, uint256[] calldata age_,
uint8[] calldata v, bytes32[] calldata r, bytes32[] calldata s) external
{
require(val_.length == bar, "Median/bar-too-low");
uint256 bloom = 0;
uint256 last = 0;
uint256 zzz = age;
for (uint i = 0; i < val_.length; i++) {
// Validate the values were signed by an authorized oracle
address signer = recover(val_[i], age_[i], v[i], r[i], s[i]);
// Check that signer is an oracle
require(orcl[signer] == 1, "Median/invalid-oracle");
// Price feed age greater than last medianizer age
require(age_[i] > zzz, "Median/stale-message");
// Check for ordered values
require(val_[i] >= last, "Median/messages-not-in-order");
last = val_[i];
// Bloom filter for signer uniqueness
uint8 sl = uint8(uint256(signer) >> 152);
require((bloom >> sl) % 2 == 0, "Median/oracle-already-signed");
bloom += uint256(2) ** sl;
}
val = uint128(val_[val_.length >> 1]);
age = uint32(block.timestamp);
emit LogMedianPrice(val, age);
}
function lift(address[] calldata a) external note auth {
for (uint i = 0; i < a.length; i++) {
require(a[i] != address(0), "Median/no-oracle-0");
uint8 s = uint8(uint256(a[i]) >> 152);
require(slot[s] == address(0), "Median/signer-already-exists");
orcl[a[i]] = 1;
slot[s] = a[i];
}
}
function drop(address[] calldata a) external note auth {
for (uint i = 0; i < a.length; i++) {
orcl[a[i]] = 0;
slot[uint8(uint256(a[i]) >> 152)] = address(0);
}
}
function setBar(uint256 bar_) external note auth {
require(bar_ > 0, "Median/quorum-is-zero");
require(bar_ % 2 != 0, "Median/quorum-not-odd-number");
bar = bar_;
}
function kiss(address a) external note auth {
require(a != address(0), "Median/no-contract-0");
bud[a] = 1;
}
function diss(address a) external note auth {
bud[a] = 0;
}
function kiss(address[] calldata a) external note auth {
for(uint i = 0; i < a.length; i++) {
require(a[i] != address(0), "Median/no-contract-0");
bud[a[i]] = 1;
}
}
function diss(address[] calldata a) external note auth {
for(uint i = 0; i < a.length; i++) {
bud[a[i]] = 0;
}
}
}
contract MedianETHUSD is Median {
bytes32 public constant wat = "ETHUSD";
function recover(uint256 val_, uint256 age_, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
return ecrecover(
keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(abi.encodePacked(val_, age_, wat)))),
v, r, s
);
}
}File 10 of 12: MedianBTCUSD
// median.sol - Medianizer v2
// Copyright (C) 2019 Maker Foundation
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.5.10;
contract LibNote {
event LogNote(
bytes4 indexed sig,
address indexed usr,
bytes32 indexed arg1,
bytes32 indexed arg2,
bytes data
) anonymous;
modifier note {
_;
assembly {
// log an 'anonymous' event with a constant 6 words of calldata
// and four indexed topics: selector, caller, arg1 and arg2
let mark := msize // end of memory ensures zero
mstore(0x40, add(mark, 288)) // update free memory pointer
mstore(mark, 0x20) // bytes type data offset
mstore(add(mark, 0x20), 224) // bytes size (padded)
calldatacopy(add(mark, 0x40), 0, 224) // bytes payload
log4(mark, 288, // calldata
shl(224, shr(224, calldataload(0))), // msg.sig
caller, // msg.sender
calldataload(4), // arg1
calldataload(36) // arg2
)
}
}
}
contract Median is LibNote {
// --- Auth ---
mapping (address => uint) public wards;
function rely(address usr) external note auth { wards[usr] = 1; }
function deny(address usr) external note auth { wards[usr] = 0; }
modifier auth {
require(wards[msg.sender] == 1, "Median/not-authorized");
_;
}
uint128 val;
uint32 public age;
bytes32 public constant wat = "ethusd"; // You want to change this every deploy
uint256 public bar = 1;
// Authorized oracles, set by an auth
mapping (address => uint256) public orcl;
// Whitelisted contracts, set by an auth
mapping (address => uint256) public bud;
// Mapping for at most 256 oracles
mapping (uint8 => address) public slot;
modifier toll { require(bud[msg.sender] == 1, "Median/contract-not-whitelisted"); _;}
event LogMedianPrice(uint256 val, uint256 age);
//Set type of Oracle
constructor() public {
wards[msg.sender] = 1;
}
function read() external view toll returns (uint256) {
require(val > 0, "Median/invalid-price-feed");
return val;
}
function peek() external view toll returns (uint256,bool) {
return (val, val > 0);
}
function recover(uint256 val_, uint256 age_, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
return ecrecover(
keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(abi.encodePacked(val_, age_, wat)))),
v, r, s
);
}
function poke(
uint256[] calldata val_, uint256[] calldata age_,
uint8[] calldata v, bytes32[] calldata r, bytes32[] calldata s) external
{
require(val_.length == bar, "Median/bar-too-low");
uint256 bloom = 0;
uint256 last = 0;
uint256 zzz = age;
for (uint i = 0; i < val_.length; i++) {
// Validate the values were signed by an authorized oracle
address signer = recover(val_[i], age_[i], v[i], r[i], s[i]);
// Check that signer is an oracle
require(orcl[signer] == 1, "Median/invalid-oracle");
// Price feed age greater than last medianizer age
require(age_[i] > zzz, "Median/stale-message");
// Check for ordered values
require(val_[i] >= last, "Median/messages-not-in-order");
last = val_[i];
// Bloom filter for signer uniqueness
uint8 sl = uint8(uint256(signer) >> 152);
require((bloom >> sl) % 2 == 0, "Median/oracle-already-signed");
bloom += uint256(2) ** sl;
}
val = uint128(val_[val_.length >> 1]);
age = uint32(block.timestamp);
emit LogMedianPrice(val, age);
}
function lift(address[] calldata a) external note auth {
for (uint i = 0; i < a.length; i++) {
require(a[i] != address(0), "Median/no-oracle-0");
uint8 s = uint8(uint256(a[i]) >> 152);
require(slot[s] == address(0), "Median/signer-already-exists");
orcl[a[i]] = 1;
slot[s] = a[i];
}
}
function drop(address[] calldata a) external note auth {
for (uint i = 0; i < a.length; i++) {
orcl[a[i]] = 0;
slot[uint8(uint256(a[i]) >> 152)] = address(0);
}
}
function setBar(uint256 bar_) external note auth {
require(bar_ > 0, "Median/quorum-is-zero");
require(bar_ % 2 != 0, "Median/quorum-not-odd-number");
bar = bar_;
}
function kiss(address a) external note auth {
require(a != address(0), "Median/no-contract-0");
bud[a] = 1;
}
function diss(address a) external note auth {
bud[a] = 0;
}
function kiss(address[] calldata a) external note auth {
for(uint i = 0; i < a.length; i++) {
require(a[i] != address(0), "Median/no-contract-0");
bud[a[i]] = 1;
}
}
function diss(address[] calldata a) external note auth {
for(uint i = 0; i < a.length; i++) {
bud[a[i]] = 0;
}
}
}
contract MedianBTCUSD is Median {
bytes32 public constant wat = "BTCUSD";
function recover(uint256 val_, uint256 age_, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
return ecrecover(
keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(abi.encodePacked(val_, age_, wat)))),
v, r, s
);
}
}File 11 of 12: MedianWSTETHUSD
// Copyright (C) 2017-2020 Maker Ecosystem Growth Holdings, INC.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pragma solidity >=0.5.10;
contract LibNote {
event LogNote(
bytes4 indexed sig,
address indexed usr,
bytes32 indexed arg1,
bytes32 indexed arg2,
bytes data
) anonymous;
modifier note {
_;
assembly {
// log an 'anonymous' event with a constant 6 words of calldata
// and four indexed topics: selector, caller, arg1 and arg2
let mark := msize() // end of memory ensures zero
mstore(0x40, add(mark, 288)) // update free memory pointer
mstore(mark, 0x20) // bytes type data offset
mstore(add(mark, 0x20), 224) // bytes size (padded)
calldatacopy(add(mark, 0x40), 0, 224) // bytes payload
log4(
mark, 288, // calldata
shl(224, shr(224, calldataload(0))), // msg.sig
caller(), // msg.sender
calldataload(4), // arg1
calldataload(36) // arg2
)
}
}
}
contract MedianWSTETHUSD is LibNote {
mapping(address => uint) public wards;
function rely(address usr) external note auth {wards[usr] = 1;}
function deny(address usr) external note auth {wards[usr] = 0;}
modifier auth {
require(wards[msg.sender] == 1, "Median/not-authorized");
_;
}
uint128 val;
uint32 public age;
bytes32 public constant wat = "WSTETHUSD";
uint256 public bar = 1;
// Authorized oracles, set by an auth
mapping(address => uint256) public orcl;
// Permitted contracts, set by an auth
mapping(address => uint256) public bud;
// Mapping for at most 256 oracles
mapping(uint8 => address) public slot;
modifier toll {
require(bud[msg.sender] == 1, "Median/contract-not-whitelisted");
_;
}
event LogMedianPrice(uint256 val, uint256 age);
//Set type of Oracle
constructor() public {
wards[msg.sender] = 1;
}
function read() external view toll returns (uint256) {
require(val > 0, "Median/invalid-price-feed");
return val;
}
function peek() external view toll returns (uint256, bool) {
return (val, val > 0);
}
function recover(uint256 val_, uint256 age_, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
return ecrecover(
keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(abi.encodePacked(val_, age_, wat)))),
v, r, s
);
}
function poke(
uint256[] calldata val_, uint256[] calldata age_,
uint8[] calldata v, bytes32[] calldata r, bytes32[] calldata s) external
{
require(val_.length == bar, "Median/bar-too-low");
uint256 bloom = 0;
uint256 last = 0;
uint256 zzz = age;
for (uint i = 0; i < val_.length; i++) {
// Validate the values were signed by an authorized oracle
address signer = recover(val_[i], age_[i], v[i], r[i], s[i]);
// Check that signer is an oracle
require(orcl[signer] == 1, "Median/invalid-oracle");
// Price feed age greater than last medianizer age
require(age_[i] > zzz, "Median/stale-message");
// Check for ordered values
require(val_[i] >= last, "Median/messages-not-in-order");
last = val_[i];
// Bloom filter for signer uniqueness
uint8 sl = uint8(uint256(signer) >> 152);
require((bloom >> sl) % 2 == 0, "Median/oracle-already-signed");
bloom += uint256(2) ** sl;
}
val = uint128(val_[val_.length >> 1]);
age = uint32(block.timestamp);
emit LogMedianPrice(val, age);
}
function lift(address[] calldata a) external note auth {
for (uint i = 0; i < a.length; i++) {
require(a[i] != address(0), "Median/no-oracle-0");
uint8 s = uint8(uint256(a[i]) >> 152);
require(slot[s] == address(0), "Median/signer-already-exists");
orcl[a[i]] = 1;
slot[s] = a[i];
}
}
function drop(address[] calldata a) external note auth {
for (uint i = 0; i < a.length; i++) {
orcl[a[i]] = 0;
slot[uint8(uint256(a[i]) >> 152)] = address(0);
}
}
function setBar(uint256 bar_) external note auth {
require(bar_ > 0, "Median/quorum-is-zero");
require(bar_ % 2 != 0, "Median/quorum-not-odd-number");
bar = bar_;
}
function kiss(address a) external note auth {
require(a != address(0), "Median/no-contract-0");
bud[a] = 1;
}
function kiss(address[] calldata a) external note auth {
for (uint i = 0; i < a.length; i++) {
require(a[i] != address(0), "Median/no-contract-0");
bud[a[i]] = 1;
}
}
function diss(address a) external note auth {
bud[a] = 0;
}
function diss(address[] calldata a) external note auth {
for (uint i = 0; i < a.length; i++) {
bud[a[i]] = 0;
}
}
}File 12 of 12: MedianMKRUSD
/// median.sol
// Copyright (C) 2017-2020 Maker Ecosystem Growth Holdings, INC.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pragma solidity >=0.5.10;
contract LibNote {
event LogNote(
bytes4 indexed sig,
address indexed usr,
bytes32 indexed arg1,
bytes32 indexed arg2,
bytes data
) anonymous;
modifier note {
_;
assembly {
// log an 'anonymous' event with a constant 6 words of calldata
// and four indexed topics: selector, caller, arg1 and arg2
let mark := msize() // end of memory ensures zero
mstore(0x40, add(mark, 288)) // update free memory pointer
mstore(mark, 0x20) // bytes type data offset
mstore(add(mark, 0x20), 224) // bytes size (padded)
calldatacopy(add(mark, 0x40), 0, 224) // bytes payload
log4(mark, 288, // calldata
shl(224, shr(224, calldataload(0))), // msg.sig
caller(), // msg.sender
calldataload(4), // arg1
calldataload(36) // arg2
)
}
}
}
contract Median is LibNote {
// --- Auth ---
mapping (address => uint) public wards;
function rely(address usr) external note auth { wards[usr] = 1; }
function deny(address usr) external note auth { wards[usr] = 0; }
modifier auth {
require(wards[msg.sender] == 1, "Median/not-authorized");
_;
}
uint128 val;
uint32 public age;
bytes32 public constant wat = "ethusd"; // You want to change this every deploy
uint256 public bar = 1;
// Authorized oracles, set by an auth
mapping (address => uint256) public orcl;
// Whitelisted contracts, set by an auth
mapping (address => uint256) public bud;
// Mapping for at most 256 oracles
mapping (uint8 => address) public slot;
modifier toll { require(bud[msg.sender] == 1, "Median/contract-not-whitelisted"); _;}
event LogMedianPrice(uint256 val, uint256 age);
//Set type of Oracle
constructor() public {
wards[msg.sender] = 1;
}
function read() external view toll returns (uint256) {
require(val > 0, "Median/invalid-price-feed");
return val;
}
function peek() external view toll returns (uint256,bool) {
return (val, val > 0);
}
function recover(uint256 val_, uint256 age_, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
return ecrecover(
keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(abi.encodePacked(val_, age_, wat)))),
v, r, s
);
}
function poke(
uint256[] calldata val_, uint256[] calldata age_,
uint8[] calldata v, bytes32[] calldata r, bytes32[] calldata s) external
{
require(val_.length == bar, "Median/bar-too-low");
uint256 bloom = 0;
uint256 last = 0;
uint256 zzz = age;
for (uint i = 0; i < val_.length; i++) {
// Validate the values were signed by an authorized oracle
address signer = recover(val_[i], age_[i], v[i], r[i], s[i]);
// Check that signer is an oracle
require(orcl[signer] == 1, "Median/invalid-oracle");
// Price feed age greater than last medianizer age
require(age_[i] > zzz, "Median/stale-message");
// Check for ordered values
require(val_[i] >= last, "Median/messages-not-in-order");
last = val_[i];
// Bloom filter for signer uniqueness
uint8 sl = uint8(uint256(signer) >> 152);
require((bloom >> sl) % 2 == 0, "Median/oracle-already-signed");
bloom += uint256(2) ** sl;
}
val = uint128(val_[val_.length >> 1]);
age = uint32(block.timestamp);
emit LogMedianPrice(val, age);
}
function lift(address[] calldata a) external note auth {
for (uint i = 0; i < a.length; i++) {
require(a[i] != address(0), "Median/no-oracle-0");
uint8 s = uint8(uint256(a[i]) >> 152);
require(slot[s] == address(0), "Median/signer-already-exists");
orcl[a[i]] = 1;
slot[s] = a[i];
}
}
function drop(address[] calldata a) external note auth {
for (uint i = 0; i < a.length; i++) {
orcl[a[i]] = 0;
slot[uint8(uint256(a[i]) >> 152)] = address(0);
}
}
function setBar(uint256 bar_) external note auth {
require(bar_ > 0, "Median/quorum-is-zero");
require(bar_ % 2 != 0, "Median/quorum-not-odd-number");
bar = bar_;
}
function kiss(address a) external note auth {
require(a != address(0), "Median/no-contract-0");
bud[a] = 1;
}
function diss(address a) external note auth {
bud[a] = 0;
}
function kiss(address[] calldata a) external note auth {
for(uint i = 0; i < a.length; i++) {
require(a[i] != address(0), "Median/no-contract-0");
bud[a[i]] = 1;
}
}
function diss(address[] calldata a) external note auth {
for(uint i = 0; i < a.length; i++) {
bud[a[i]] = 0;
}
}
}
contract MedianMKRUSD is Median {
bytes32 public constant wat = "MKRUSD";
function recover(uint256 val_, uint256 age_, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
return ecrecover(
keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(abi.encodePacked(val_, age_, wat)))),
v, r, s
);
}
}