ETH Price: $2,035.53 (-2.76%)

Transaction Decoder

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 Code
(Titan Builder)
11.210232280533551461 Eth11.210233456919151461 Eth0.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( )
            File 1 of 12: OracleJob
            // 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
                    );
                }
            }