ETH Price: $1,928.55 (+1.36%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Cast207701912024-09-17 12:00:23179 days ago1726574423IN
0x70254BD5...AAE6130b6
0 ETH0.00813082.8348571
Schedule207493472024-09-14 14:08:35181 days ago1726322915IN
0x70254BD5...AAE6130b6
0 ETH0.000253192.72858747

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x60a06040207411862024-09-13 10:45:59183 days ago1726224359
0x70254BD5...AAE6130b6
 Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
DssSpell

Compiler Version
v0.8.16+commit.07a7930e

Optimization Enabled:
Yes with 1 runs

Other Settings:
default evmVersion, GNU AGPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2024-09-13
*/

// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity <0.9.0 =0.8.16 >=0.5.12 >=0.6.2 >=0.8.0 ^0.8.13 ^0.8.16;
pragma experimental ABIEncoderV2;

// lib/dss-exec-lib/src/CollateralOpts.sol

//
// CollateralOpts.sol -- Data structure for onboarding collateral
//
// Copyright (C) 2020-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/>.

struct CollateralOpts {
    bytes32 ilk;
    address gem;
    address join;
    address clip;
    address calc;
    address pip;
    bool    isLiquidatable;
    bool    isOSM;
    bool    whitelistOSM;
    uint256 ilkDebtCeiling;
    uint256 minVaultAmount;
    uint256 maxLiquidationAmount;
    uint256 liquidationPenalty;
    uint256 ilkStabilityFee;
    uint256 startingPriceFactor;
    uint256 breakerTolerance;
    uint256 auctionDuration;
    uint256 permittedDrop;
    uint256 liquidationRatio;
    uint256 kprFlatReward;
    uint256 kprPctReward;
}

// lib/dss-test/lib/dss-interfaces/src/ERC/GemAbstract.sol

// A base ERC-20 abstract class
// https://eips.ethereum.org/EIPS/eip-20
interface GemAbstract {
    function totalSupply() external view returns (uint256);
    function balanceOf(address) external view returns (uint256);
    function allowance(address, address) external view returns (uint256);
    function approve(address, uint256) external returns (bool);
    function transfer(address, uint256) external returns (bool);
    function transferFrom(address, address, uint256) external returns (bool);
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);
}

// lib/dss-test/lib/dss-interfaces/src/dapp/DSAuthorityAbstract.sol

// https://github.com/dapphub/ds-auth
interface DSAuthorityAbstract {
    function canCall(address, address, bytes4) external view returns (bool);
}

interface DSAuthAbstract {
    function authority() external view returns (address);
    function owner() external view returns (address);
    function setOwner(address) external;
    function setAuthority(address) external;
}

// lib/dss-test/lib/dss-interfaces/src/dapp/DSChiefAbstract.sol

// https://github.com/dapphub/ds-chief
interface DSChiefAbstract {
    function live() external view returns (uint256);
    function launch() external;
    function slates(bytes32) external view returns (address[] memory);
    function votes(address) external view returns (bytes32);
    function approvals(address) external view returns (uint256);
    function deposits(address) external view returns (address);
    function GOV() external view returns (address);
    function IOU() external view returns (address);
    function hat() external view returns (address);
    function MAX_YAYS() external view returns (uint256);
    function lock(uint256) external;
    function free(uint256) external;
    function etch(address[] calldata) external returns (bytes32);
    function vote(address[] calldata) external returns (bytes32);
    function vote(bytes32) external;
    function lift(address) external;
    function setOwner(address) external;
    function setAuthority(address) external;
    function isUserRoot(address) external view returns (bool);
    function setRootUser(address, bool) external;
    function _root_users(address) external view returns (bool);
    function _user_roles(address) external view returns (bytes32);
    function _capability_roles(address, bytes4) external view returns (bytes32);
    function _public_capabilities(address, bytes4) external view returns (bool);
    function getUserRoles(address) external view returns (bytes32);
    function getCapabilityRoles(address, bytes4) external view returns (bytes32);
    function isCapabilityPublic(address, bytes4) external view returns (bool);
    function hasUserRole(address, uint8) external view returns (bool);
    function canCall(address, address, bytes4) external view returns (bool);
    function setUserRole(address, uint8, bool) external;
    function setPublicCapability(address, bytes4, bool) external;
    function setRoleCapability(uint8, address, bytes4, bool) external;
}

interface DSChiefFabAbstract {
    function newChief(address, uint256) external returns (address);
}

// lib/dss-test/lib/dss-interfaces/src/dapp/DSPauseAbstract.sol

// https://github.com/dapphub/ds-pause
interface DSPauseAbstract {
    function owner() external view returns (address);
    function authority() external view returns (address);
    function setOwner(address) external;
    function setAuthority(address) external;
    function setDelay(uint256) external;
    function plans(bytes32) external view returns (bool);
    function proxy() external view returns (address);
    function delay() external view returns (uint256);
    function plot(address, bytes32, bytes calldata, uint256) external;
    function drop(address, bytes32, bytes calldata, uint256) external;
    function exec(address, bytes32, bytes calldata, uint256) external returns (bytes memory);
}

// lib/dss-test/lib/dss-interfaces/src/dapp/DSPauseProxyAbstract.sol

// https://github.com/dapphub/ds-pause
interface DSPauseProxyAbstract {
    function owner() external view returns (address);
    function exec(address, bytes calldata) external returns (bytes memory);
}

// lib/dss-test/lib/dss-interfaces/src/dapp/DSRolesAbstract.sol

// https://github.com/dapphub/ds-roles
interface DSRolesAbstract {
    function _root_users(address) external view returns (bool);
    function _user_roles(address) external view returns (bytes32);
    function _capability_roles(address, bytes4) external view returns (bytes32);
    function _public_capabilities(address, bytes4) external view returns (bool);
    function getUserRoles(address) external view returns (bytes32);
    function getCapabilityRoles(address, bytes4) external view returns (bytes32);
    function isUserRoot(address) external view returns (bool);
    function isCapabilityPublic(address, bytes4) external view returns (bool);
    function hasUserRole(address, uint8) external view returns (bool);
    function canCall(address, address, bytes4) external view returns (bool);
    function setRootUser(address, bool) external;
    function setUserRole(address, uint8, bool) external;
    function setPublicCapability(address, bytes4, bool) external;
    function setRoleCapability(uint8, address, bytes4, bool) external;
    function authority() external view returns (address);
    function owner() external view returns (address);
    function setOwner(address) external;
    function setAuthority(address) external;
}

// lib/dss-test/lib/dss-interfaces/src/dapp/DSRuneAbstract.sol

// Copyright (C) 2020 Maker 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/>.

// https://github.com/makerdao/dss-spellbook
interface DSRuneAbstract {
    // @return [address] A contract address conforming to DSPauseAbstract
    function pause()    external view returns (address);
    // @return [address] The address of the contract to be executed
    // TODO: is `action()` a required field? Not all spells rely on a seconary contract.
    function action()   external view returns (address);
    // @return [bytes32] extcodehash of rune address
    function tag()      external view returns (bytes32);
    // @return [bytes] The `abi.encodeWithSignature()` result of the function to be called.
    function sig()      external view returns (bytes memory);
    // @return [uint256] Earliest time rune can execute
    function eta()      external view returns (uint256);
    // The schedule() function plots the rune in the DSPause
    function schedule() external;
    // @return [bool] true if the rune has been cast()
    function done()     external view returns (bool);
    // The cast() function executes the rune
    function cast()     external;
}

// lib/dss-test/lib/dss-interfaces/src/dapp/DSSpellAbstract.sol

// https://github.com/dapphub/ds-spell
interface DSSpellAbstract {
    function whom() external view returns (address);
    function mana() external view returns (uint256);
    function data() external view returns (bytes memory);
    function done() external view returns (bool);
    function cast() external;
}

// lib/dss-test/lib/dss-interfaces/src/dapp/DSThingAbstract.sol

// https://github.com/dapphub/ds-thing
interface DSThingAbstract {
    function authority() external view returns (address);
    function owner() external view returns (address);
    function setOwner(address) external;
    function setAuthority(address) external;
}

// lib/dss-test/lib/dss-interfaces/src/dapp/DSTokenAbstract.sol

// https://github.com/dapphub/ds-token/blob/master/src/token.sol
interface DSTokenAbstract {
    function name() external view returns (bytes32);
    function symbol() external view returns (bytes32);
    function decimals() external view returns (uint256);
    function totalSupply() external view returns (uint256);
    function balanceOf(address) external view returns (uint256);
    function transfer(address, uint256) external returns (bool);
    function allowance(address, address) external view returns (uint256);
    function approve(address, uint256) external returns (bool);
    function approve(address) external returns (bool);
    function transferFrom(address, address, uint256) external returns (bool);
    function push(address, uint256) external;
    function pull(address, uint256) external;
    function move(address, address, uint256) external;
    function mint(uint256) external;
    function mint(address,uint) external;
    function burn(uint256) external;
    function burn(address,uint) external;
    function setName(bytes32) external;
    function authority() external view returns (address);
    function owner() external view returns (address);
    function setOwner(address) external;
    function setAuthority(address) external;
}

// lib/dss-test/lib/dss-interfaces/src/dapp/DSValueAbstract.sol

// https://github.com/dapphub/ds-value/blob/master/src/value.sol
interface DSValueAbstract {
    function has() external view returns (bool);
    function val() external view returns (bytes32);
    function peek() external view returns (bytes32, bool);
    function read() external view returns (bytes32);
    function poke(bytes32) external;
    function void() external;
    function authority() external view returns (address);
    function owner() external view returns (address);
    function setOwner(address) external;
    function setAuthority(address) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/AuthGemJoinAbstract.sol

// https://github.com/makerdao/dss-deploy/blob/master/src/join.sol
interface AuthGemJoinAbstract {
    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);
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function cage() external;
    function join(address, uint256) external;
    function exit(address, uint256) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/CatAbstract.sol

// https://github.com/makerdao/dss/blob/master/src/cat.sol
interface CatAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function box() external view returns (uint256);
    function litter() external view returns (uint256);
    function ilks(bytes32) external view returns (address, uint256, uint256);
    function live() external view returns (uint256);
    function vat() external view returns (address);
    function vow() external view returns (address);
    function file(bytes32, address) external;
    function file(bytes32, uint256) external;
    function file(bytes32, bytes32, uint256) external;
    function file(bytes32, bytes32, address) external;
    function bite(bytes32, address) external returns (uint256);
    function claw(uint256) external;
    function cage() external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/ChainlogAbstract.sol

// https://github.com/makerdao/dss-chain-log
interface ChainlogAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function keys() external view returns (bytes32[] memory);
    function version() external view returns (string memory);
    function ipfs() external view returns (string memory);
    function setVersion(string calldata) external;
    function setSha256sum(string calldata) external;
    function setIPFS(string calldata) external;
    function setAddress(bytes32,address) external;
    function removeAddress(bytes32) external;
    function count() external view returns (uint256);
    function get(uint256) external view returns (bytes32,address);
    function list() external view returns (bytes32[] memory);
    function getAddress(bytes32) external view returns (address);
}

// Helper function for returning address or abstract of Chainlog
//  Valid on Mainnet, Kovan, Rinkeby, Ropsten, and Goerli
contract ChainlogHelper {
    address          public constant ADDRESS  = 0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F;
    ChainlogAbstract public constant ABSTRACT = ChainlogAbstract(ADDRESS);
}

// lib/dss-test/lib/dss-interfaces/src/dss/ClipAbstract.sol

/// ClipAbstract.sol -- Clip Interface

// Copyright (C) 2021 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/>.

interface ClipAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function ilk() external view returns (bytes32);
    function vat() external view returns (address);
    function dog() external view returns (address);
    function vow() external view returns (address);
    function spotter() external view returns (address);
    function calc() external view returns (address);
    function buf() external view returns (uint256);
    function tail() external view returns (uint256);
    function cusp() external view returns (uint256);
    function chip() external view returns (uint64);
    function tip() external view returns (uint192);
    function chost() external view returns (uint256);
    function kicks() external view returns (uint256);
    function active(uint256) external view returns (uint256);
    function sales(uint256) external view returns (uint256,uint256,uint256,address,uint96,uint256);
    function stopped() external view returns (uint256);
    function file(bytes32,uint256) external;
    function file(bytes32,address) external;
    function kick(uint256,uint256,address,address) external returns (uint256);
    function redo(uint256,address) external;
    function take(uint256,uint256,uint256,address,bytes calldata) external;
    function count() external view returns (uint256);
    function list() external view returns (uint256[] memory);
    function getStatus(uint256) external view returns (bool,uint256,uint256,uint256);
    function upchost() external;
    function yank(uint256) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/ClipperMomAbstract.sol

// https://github.com/makerdao/Clipper-mom/blob/master/src/ClipperMom.sol
interface ClipperMomAbstract {
    function owner() external view returns (address);
    function authority() external view returns (address);
    function locked(address) external view returns (uint256);
    function tolerance(address) external view returns (uint256);
    function spotter() external view returns (address);
    function setOwner(address) external;
    function setAuthority(address) external;
    function setPriceTolerance(address, uint256) external;
    function setBreaker(address, uint256, uint256) external;
    function tripBreaker(address) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/CureAbstract.sol

// https://github.com/makerdao/dss/blob/master/src/cure.sol
interface CureAbstract {
    function wards(address) external view returns (uint256);
    function live() external view returns (uint256);
    function srcs(uint256) external view returns (address);
    function wait() external view returns (uint256);
    function when() external view returns (uint256);
    function pos(address) external view returns (uint256);
    function amt(address) external view returns (uint256);
    function loadded(address) external view returns (uint256);
    function lCount() external view returns (uint256);
    function say() external view returns (uint256);
    function tCount() external view returns (uint256);
    function list() external view returns (address[] memory);
    function tell() external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function file(bytes32, uint256) external;
    function lift(address) external;
    function drop(address) external;
    function cage() external;
    function load(address) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/DaiAbstract.sol

// https://github.com/makerdao/dss/blob/master/src/dai.sol
interface DaiAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function version() external view returns (string memory);
    function decimals() external view returns (uint8);
    function totalSupply() external view returns (uint256);
    function balanceOf(address) external view returns (uint256);
    function allowance(address, address) external view returns (uint256);
    function nonces(address) external view returns (uint256);
    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external view returns (bytes32);
    function transfer(address, uint256) external returns (bool);
    function transferFrom(address, address, uint256) external returns (bool);
    function mint(address, uint256) external;
    function burn(address, uint256) external;
    function approve(address, uint256) external returns (bool);
    function push(address, uint256) external;
    function pull(address, uint256) external;
    function move(address, address, uint256) external;
    function permit(address, address, uint256, uint256, bool, uint8, bytes32, bytes32) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/DaiJoinAbstract.sol

// https://github.com/makerdao/dss/blob/master/src/join.sol
interface DaiJoinAbstract {
    function wards(address) external view returns (uint256);
    function rely(address usr) external;
    function deny(address usr) external;
    function vat() external view returns (address);
    function dai() external view returns (address);
    function live() external view returns (uint256);
    function cage() external;
    function join(address, uint256) external;
    function exit(address, uint256) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/DogAbstract.sol

/// DogAbstract.sol -- Dog Interface

// Copyright (C) 2021 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/>.

interface DogAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function vat() external view returns (address);
    function ilks(bytes32) external view returns (address,uint256,uint256,uint256);
    function vow() external view returns (address);
    function live() external view returns (uint256);
    function Hole() external view returns (uint256);
    function Dirt() external view returns (uint256);
    function file(bytes32,address) external;
    function file(bytes32,uint256) external;
    function file(bytes32,bytes32,uint256) external;
    function file(bytes32,bytes32,address) external;
    function chop(bytes32) external view returns (uint256);
    function bark(bytes32,address,address) external returns (uint256);
    function digs(bytes32,uint256) external;
    function cage() external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/DssAutoLineAbstract.sol

// https://github.com/makerdao/dss-auto-line/blob/master/src/DssAutoLine.sol
interface DssAutoLineAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function vat() external view returns (address);
    function ilks(bytes32) external view returns (uint256,uint256,uint48,uint48,uint48);
    function setIlk(bytes32,uint256,uint256,uint256) external;
    function remIlk(bytes32) external;
    function exec(bytes32) external returns (uint256);
}

// lib/dss-test/lib/dss-interfaces/src/dss/DssCdpManager.sol

// https://github.com/makerdao/dss-cdp-manager/
interface DssCdpManagerAbstract {
    function vat() external view returns (address);
    function cdpi() external view returns (uint256);
    function urns(uint256) external view returns (address);
    function list(uint256) external view returns (uint256,uint256);
    function owns(uint256) external view returns (address);
    function ilks(uint256) external view returns (bytes32);
    function first(address) external view returns (uint256);
    function last(address) external view returns (uint256);
    function count(address) external view returns (uint256);
    function cdpCan(address, uint256, address) external returns (uint256);
    function urnCan(address, address) external returns (uint256);
    function cdpAllow(uint256, address, uint256) external;
    function urnAllow(address, uint256) external;
    function open(bytes32, address) external returns (uint256);
    function give(uint256, address) external;
    function frob(uint256, int256, int256) external;
    function flux(uint256, address, uint256) external;
    function flux(bytes32, uint256, address, uint256) external;
    function move(uint256, address, uint256) external;
    function quit(uint256, address) external;
    function enter(address, uint256) external;
    function shift(uint256, uint256) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/ESMAbstract.sol

// https://github.com/makerdao/esm/blob/master/src/ESM.sol
interface ESMAbstract {
    function gem() external view returns (address);
    function proxy() external view returns (address);
    function wards(address) external view returns (uint256);
    function sum(address) external view returns (address);
    function Sum() external view returns (uint256);
    function min() external view returns (uint256);
    function end() external view returns (address);
    function live() external view returns (uint256);
    function revokesGovernanceAccess() external view returns (bool);
    function rely(address) external;
    function deny(address) external;
    function file(bytes32, uint256) external;
    function file(bytes32, address) external;
    function cage() external;
    function fire() external;
    function denyProxy(address) external;
    function join(uint256) external;
    function burn() external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/ETHJoinAbstract.sol

// https://github.com/makerdao/dss/blob/master/src/join.sol
interface ETHJoinAbstract {
    function wards(address) external view returns (uint256);
    function rely(address usr) external;
    function deny(address usr) external;
    function vat() external view returns (address);
    function ilk() external view returns (bytes32);
    function live() external view returns (uint256);
    function cage() external;
    function join(address) external payable;
    function exit(address, uint256) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/EndAbstract.sol

// https://github.com/makerdao/dss/blob/master/src/end.sol
interface EndAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function vat() external view returns (address);
    function cat() external view returns (address);
    function dog() external view returns (address);
    function vow() external view returns (address);
    function pot() external view returns (address);
    function spot() external view returns (address);
    function cure() external view returns (address);
    function live() external view returns (uint256);
    function when() external view returns (uint256);
    function wait() external view returns (uint256);
    function debt() external view returns (uint256);
    function tag(bytes32) external view returns (uint256);
    function gap(bytes32) external view returns (uint256);
    function Art(bytes32) external view returns (uint256);
    function fix(bytes32) external view returns (uint256);
    function bag(address) external view returns (uint256);
    function out(bytes32, address) external view returns (uint256);
    function file(bytes32, address) external;
    function file(bytes32, uint256) external;
    function cage() external;
    function cage(bytes32) external;
    function skip(bytes32, uint256) external;
    function snip(bytes32, uint256) external;
    function skim(bytes32, address) external;
    function free(bytes32) external;
    function thaw() external;
    function flow(bytes32) external;
    function pack(uint256) external;
    function cash(bytes32, uint256) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/ExponentialDecreaseAbstract.sol

/// ExponentialDecreaseAbstract.sol -- Exponential Decrease Interface

// Copyright (C) 2021 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/>.

interface ExponentialDecreaseAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function cut() external view returns (uint256);
    function file(bytes32,uint256) external;
    function price(uint256,uint256) external view returns (uint256);
}

// lib/dss-test/lib/dss-interfaces/src/dss/FaucetAbstract.sol

// https://github.com/makerdao/token-faucet/blob/master/src/RestrictedTokenFaucet.sol
interface FaucetAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function list(address) external view returns (uint256);
    function hope(address) external;
    function nope(address) external;
    function amt(address) external view returns (uint256);
    function done(address, address) external view returns (bool);
    function gulp(address) external;
    function gulp(address, address[] calldata) external;
    function shut(address) external;
    function undo(address, address) external;
    function setAmt(address, uint256) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/FlapAbstract.sol

// https://github.com/makerdao/dss/blob/master/src/flap.sol
interface FlapAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function bids(uint256) external view returns (uint256, uint256, address, uint48, uint48);
    function vat() external view returns (address);
    function gem() external view returns (address);
    function beg() external view returns (uint256);
    function ttl() external view returns (uint48);
    function tau() external view returns (uint48);
    function kicks() external view returns (uint256);
    function live() external view returns (uint256);
    function lid() external view returns (uint256);
    function fill() external view returns (uint256);
    function file(bytes32, uint256) external;
    function kick(uint256, uint256) external returns (uint256);
    function tick(uint256) external;
    function tend(uint256, uint256, uint256) external;
    function deal(uint256) external;
    function cage(uint256) external;
    function yank(uint256) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/FlashAbstract.sol

// https://github.com/makerdao/dss-flash/blob/master/src/flash.sol
interface FlashAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function vat() external view returns (address);
    function daiJoin() external view returns (address);
    function dai() external view returns (address);
    function vow() external view returns (address);
    function max() external view returns (uint256);
    function toll() external view returns (uint256);
    function CALLBACK_SUCCESS() external view returns (bytes32);
    function CALLBACK_SUCCESS_VAT_DAI() external view returns (bytes32);
    function file(bytes32, uint256) external;
    function maxFlashLoan(address) external view returns (uint256);
    function flashFee(address, uint256) external view returns (uint256);
    function flashLoan(address, address, uint256, bytes calldata) external returns (bool);
    function vatDaiFlashLoan(address, uint256, bytes calldata) external returns (bool);
    function convert() external;
    function accrue() external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/FlipAbstract.sol

// https://github.com/makerdao/dss/blob/master/src/flip.sol
interface FlipAbstract {
    function wards(address) external view returns (uint256);
    function rely(address usr) external;
    function deny(address usr) external;
    function bids(uint256) external view returns (uint256, uint256, address, uint48, uint48, address, address, uint256);
    function vat() external view returns (address);
    function cat() external view returns (address);
    function ilk() external view returns (bytes32);
    function beg() external view returns (uint256);
    function ttl() external view returns (uint48);
    function tau() external view returns (uint48);
    function kicks() external view returns (uint256);
    function file(bytes32, uint256) external;
    function kick(address, address, uint256, uint256, uint256) external returns (uint256);
    function tick(uint256) external;
    function tend(uint256, uint256, uint256) external;
    function dent(uint256, uint256, uint256) external;
    function deal(uint256) external;
    function yank(uint256) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/FlipperMomAbstract.sol

// https://github.com/makerdao/flipper-mom/blob/master/src/FlipperMom.sol
interface FlipperMomAbstract {
    function owner() external view returns (address);
    function authority() external view returns (address);
    function setOwner(address) external;
    function setAuthority(address) external;
    function cat() external returns (address);
    function rely(address) external;
    function deny(address) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/FlopAbstract.sol

// https://github.com/makerdao/dss/blob/master/src/flop.sol
interface FlopAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function bids(uint256) external view returns (uint256, uint256, address, uint48, uint48);
    function vat() external view returns (address);
    function gem() external view returns (address);
    function beg() external view returns (uint256);
    function pad() external view returns (uint256);
    function ttl() external view returns (uint48);
    function tau() external view returns (uint48);
    function kicks() external view returns (uint256);
    function live() external view returns (uint256);
    function vow() external view returns (address);
    function file(bytes32, uint256) external;
    function kick(address, uint256, uint256) external returns (uint256);
    function tick(uint256) external;
    function dent(uint256, uint256, uint256) external;
    function deal(uint256) external;
    function cage() external;
    function yank(uint256) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/GemJoinAbstract.sol

// https://github.com/makerdao/dss/blob/master/src/join.sol
interface GemJoinAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    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);
    function cage() external;
    function join(address, uint256) external;
    function exit(address, uint256) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/GemJoinImplementationAbstract.sol

// https://github.com/makerdao/dss-deploy/blob/master/src/join.sol
interface GemJoinImplementationAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    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);
    function cage() external;
    function join(address, uint256) external;
    function exit(address, uint256) external;
    function setImplementation(address, uint256) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/GemJoinManagedAbstract.sol

// https://github.com/makerdao/dss-gem-joins/blob/master/src/join-managed.sol
interface GemJoinManagedAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    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);
    function cage() external;
    function join(address, uint256) external;
    function exit(address, address, uint256) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/GetCdpsAbstract.sol

// https://github.com/makerdao/dss-cdp-manager/blob/master/src/GetCdps.sol
interface GetCdpsAbstract {
    function getCdpsAsc(address, address) external view returns (uint256[] memory, address[] memory, bytes32[] memory);
    function getCdpsDesc(address, address) external view returns (uint256[] memory, address[] memory, bytes32[] memory);
}

// lib/dss-test/lib/dss-interfaces/src/dss/IlkRegistryAbstract.sol

// https://github.com/makerdao/ilk-registry
interface IlkRegistryAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function vat() external view returns (address);
    function dog() external view returns (address);
    function cat() external view returns (address);
    function spot() external view returns (address);
    function ilkData(bytes32) external view returns (
        uint96, address, address, uint8, uint96, address, address, string memory, string memory
    );
    function ilks() external view returns (bytes32[] memory);
    function ilks(uint) external view returns (bytes32);
    function add(address) external;
    function remove(bytes32) external;
    function update(bytes32) external;
    function removeAuth(bytes32) external;
    function file(bytes32, address) external;
    function file(bytes32, bytes32, address) external;
    function file(bytes32, bytes32, uint256) external;
    function file(bytes32, bytes32, string calldata) external;
    function count() external view returns (uint256);
    function list() external view returns (bytes32[] memory);
    function list(uint256, uint256) external view returns (bytes32[] memory);
    function get(uint256) external view returns (bytes32);
    function info(bytes32) external view returns (
        string memory, string memory, uint256, uint256, address, address, address, address
    );
    function pos(bytes32) external view returns (uint256);
    function class(bytes32) external view returns (uint256);
    function gem(bytes32) external view returns (address);
    function pip(bytes32) external view returns (address);
    function join(bytes32) external view returns (address);
    function xlip(bytes32) external view returns (address);
    function dec(bytes32) external view returns (uint256);
    function symbol(bytes32) external view returns (string memory);
    function name(bytes32) external view returns (string memory);
    function put(bytes32, address, address, uint256, uint256, address, address, string calldata, string calldata) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/JugAbstract.sol

// https://github.com/makerdao/dss/blob/master/src/jug.sol
interface JugAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function ilks(bytes32) external view returns (uint256, uint256);
    function vat() external view returns (address);
    function vow() external view returns (address);
    function base() external view returns (uint256);
    function init(bytes32) external;
    function file(bytes32, bytes32, uint256) external;
    function file(bytes32, uint256) external;
    function file(bytes32, address) external;
    function drip(bytes32) external returns (uint256);
}

// lib/dss-test/lib/dss-interfaces/src/dss/LPOsmAbstract.sol

// https://github.com/makerdao/univ2-lp-oracle
interface LPOsmAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function stopped() external view returns (uint256);
    function bud(address) external view returns (uint256);
    function dec0() external view returns (uint8);
    function dec1() external view returns (uint8);
    function orb0() external view returns (address);
    function orb1() external view returns (address);
    function wat() external view returns (bytes32);
    function hop() external view returns (uint32);
    function src() external view returns (address);
    function zzz() external view returns (uint64);
    function change(address) external;
    function step(uint256) external;
    function stop() external;
    function start() external;
    function pass() external view returns (bool);
    function poke() external;
    function peek() external view returns (bytes32, bool);
    function peep() external view returns (bytes32, bool);
    function read() external view returns (bytes32);
    function kiss(address) external;
    function diss(address) external;
    function kiss(address[] calldata) external;
    function diss(address[] calldata) external;
    function link(uint256, address) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/LerpAbstract.sol

// https://github.com/makerdao/dss-lerp/blob/master/src/Lerp.sol
interface LerpAbstract {
    function target() external view returns (address);
    function what() external view returns (bytes32);
    function start() external view returns (uint256);
    function end() external view returns (uint256);
    function duration() external view returns (uint256);
    function done() external view returns (bool);
    function startTime() external view returns (uint256);
    function tick() external returns (uint256);
    function ilk() external view returns (bytes32);
}

// lib/dss-test/lib/dss-interfaces/src/dss/LerpFactoryAbstract.sol

// https://github.com/makerdao/dss-lerp/blob/master/src/LerpFactory.sol
interface LerpFactoryAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function lerps(bytes32) external view returns (address);
    function active(uint256) external view returns (address);
    function newLerp(bytes32, address, bytes32, uint256, uint256, uint256, uint256) external returns (address);
    function newIlkLerp(bytes32, address, bytes32, bytes32, uint256, uint256, uint256, uint256) external returns (address);
    function tall() external;
    function count() external view returns (uint256);
    function list() external view returns (address[] memory);
}

// lib/dss-test/lib/dss-interfaces/src/dss/LinearDecreaseAbstract.sol

/// LinearDecreaseAbstract.sol -- Linear Decrease Interface

// Copyright (C) 2021 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/>.

interface LinearDecreaseAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function tau() external view returns (uint256);
    function file(bytes32,uint256) external;
    function price(uint256,uint256) external view returns (uint256);
}

// lib/dss-test/lib/dss-interfaces/src/dss/MedianAbstract.sol

// https://github.com/makerdao/median
interface MedianAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function age() external view returns (uint32);
    function wat() external view returns (bytes32);
    function bar() external view returns (uint256);
    function orcl(address) external view returns (uint256);
    function bud(address) external view returns (uint256);
    function slot(uint8) external view returns (address);
    function read() external view returns (uint256);
    function peek() external view returns (uint256, bool);
    function lift(address[] calldata) external;
    function drop(address[] calldata) external;
    function setBar(uint256) external;
    function kiss(address) external;
    function diss(address) external;
    function kiss(address[] calldata) external;
    function diss(address[] calldata) external;
    function poke(uint256[] calldata, uint256[] calldata, uint8[] calldata, bytes32[] calldata, bytes32[] calldata) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/MkrAuthorityAbstract.sol

// https://github.com/makerdao/mkr-authority/blob/master/src/MkrAuthority.sol
interface MkrAuthorityAbstract {
    function root() external returns (address);
    function setRoot(address) external;
    function wards(address) external returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function canCall(address, address, bytes4) external returns (bool);
}

// lib/dss-test/lib/dss-interfaces/src/dss/OsmAbstract.sol

// https://github.com/makerdao/osm
interface OsmAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function stopped() external view returns (uint256);
    function src() external view returns (address);
    function hop() external view returns (uint16);
    function zzz() external view returns (uint64);
    function bud(address) external view returns (uint256);
    function stop() external;
    function start() external;
    function change(address) external;
    function step(uint16) external;
    function void() external;
    function pass() external view returns (bool);
    function poke() external;
    function peek() external view returns (bytes32, bool);
    function peep() external view returns (bytes32, bool);
    function read() external view returns (bytes32);
    function kiss(address) external;
    function diss(address) external;
    function kiss(address[] calldata) external;
    function diss(address[] calldata) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/OsmMomAbstract.sol

// https://github.com/makerdao/osm-mom
interface OsmMomAbstract {
    function owner() external view returns (address);
    function authority() external view returns (address);
    function osms(bytes32) external view returns (address);
    function setOsm(bytes32, address) external;
    function setOwner(address) external;
    function setAuthority(address) external;
    function stop(bytes32) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/PotAbstract.sol

// https://github.com/makerdao/dss/blob/master/src/pot.sol
interface PotAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function pie(address) external view returns (uint256);
    function Pie() external view returns (uint256);
    function dsr() external view returns (uint256);
    function chi() external view returns (uint256);
    function vat() external view returns (address);
    function vow() external view returns (address);
    function rho() external view returns (uint256);
    function live() external view returns (uint256);
    function file(bytes32, uint256) external;
    function file(bytes32, address) external;
    function cage() external;
    function drip() external returns (uint256);
    function join(uint256) external;
    function exit(uint256) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/PsmAbstract.sol

// https://github.com/makerdao/dss-psm/blob/master/src/psm.sol
interface PsmAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function vat() external view returns (address);
    function gemJoin() external view returns (address);
    function dai() external view returns (address);
    function daiJoin() external view returns (address);
    function ilk() external view returns (bytes32);
    function vow() external view returns (address);
    function tin() external view returns (uint256);
    function tout() external view returns (uint256);
    function file(bytes32 what, uint256 data) external;
    function hope(address) external;
    function nope(address) external;
    function sellGem(address usr, uint256 gemAmt) external;
    function buyGem(address usr, uint256 gemAmt) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/SpotAbstract.sol

// https://github.com/makerdao/dss/blob/master/src/spot.sol
interface SpotAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function ilks(bytes32) external view returns (address, uint256);
    function vat() external view returns (address);
    function par() external view returns (uint256);
    function live() external view returns (uint256);
    function file(bytes32, bytes32, address) external;
    function file(bytes32, uint256) external;
    function file(bytes32, bytes32, uint256) external;
    function poke(bytes32) external;
    function cage() external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/StairstepExponentialDecreaseAbstract.sol

/// StairstepExponentialDecreaseAbstract.sol -- StairstepExponentialDecrease Interface

// Copyright (C) 2021 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/>.

interface StairstepExponentialDecreaseAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function step() external view returns (uint256);
    function cut() external view returns (uint256);
    function file(bytes32,uint256) external;
    function price(uint256,uint256) external view returns (uint256);
}

// lib/dss-test/lib/dss-interfaces/src/dss/VatAbstract.sol

// https://github.com/makerdao/dss/blob/master/src/vat.sol
interface VatAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function can(address, address) external view returns (uint256);
    function hope(address) external;
    function nope(address) external;
    function ilks(bytes32) external view returns (uint256, uint256, uint256, uint256, uint256);
    function urns(bytes32, address) external view returns (uint256, uint256);
    function gem(bytes32, address) external view returns (uint256);
    function dai(address) external view returns (uint256);
    function sin(address) external view returns (uint256);
    function debt() external view returns (uint256);
    function vice() external view returns (uint256);
    function Line() external view returns (uint256);
    function live() external view returns (uint256);
    function init(bytes32) external;
    function file(bytes32, uint256) external;
    function file(bytes32, bytes32, uint256) external;
    function cage() external;
    function slip(bytes32, address, int256) external;
    function flux(bytes32, address, address, uint256) external;
    function move(address, address, uint256) external;
    function frob(bytes32, address, address, address, int256, int256) external;
    function fork(bytes32, address, address, int256, int256) external;
    function grab(bytes32, address, address, address, int256, int256) external;
    function heal(uint256) external;
    function suck(address, address, uint256) external;
    function fold(bytes32, address, int256) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/VestAbstract.sol

// https://github.com/makerdao/dss-vest/blob/master/src/DssVest.sol
interface VestAbstract {
    function TWENTY_YEARS() external view returns (uint256);
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function awards(uint256) external view returns (address, uint48, uint48, uint48, address, uint8, uint128, uint128);
    function ids() external view returns (uint256);
    function cap() external view returns (uint256);
    function usr(uint256) external view returns (address);
    function bgn(uint256) external view returns (uint256);
    function clf(uint256) external view returns (uint256);
    function fin(uint256) external view returns (uint256);
    function mgr(uint256) external view returns (address);
    function res(uint256) external view returns (uint256);
    function tot(uint256) external view returns (uint256);
    function rxd(uint256) external view returns (uint256);
    function file(bytes32, uint256) external;
    function create(address, uint256, uint256, uint256, uint256, address) external returns (uint256);
    function vest(uint256) external;
    function vest(uint256, uint256) external;
    function accrued(uint256) external view returns (uint256);
    function unpaid(uint256) external view returns (uint256);
    function restrict(uint256) external;
    function unrestrict(uint256) external;
    function yank(uint256) external;
    function yank(uint256, uint256) external;
    function move(uint256, address) external;
    function valid(uint256) external view returns (bool);
}

// lib/dss-test/lib/dss-interfaces/src/dss/VowAbstract.sol

// https://github.com/makerdao/dss/blob/master/src/vow.sol
interface VowAbstract {
    function wards(address) external view returns (uint256);
    function rely(address usr) external;
    function deny(address usr) external;
    function vat() external view returns (address);
    function flapper() external view returns (address);
    function flopper() external view returns (address);
    function sin(uint256) external view returns (uint256);
    function Sin() external view returns (uint256);
    function Ash() external view returns (uint256);
    function wait() external view returns (uint256);
    function dump() external view returns (uint256);
    function sump() external view returns (uint256);
    function bump() external view returns (uint256);
    function hump() external view returns (uint256);
    function live() external view returns (uint256);
    function file(bytes32, uint256) external;
    function file(bytes32, address) external;
    function fess(uint256) external;
    function flog(uint256) external;
    function heal(uint256) external;
    function kiss(uint256) external;
    function flop() external returns (uint256);
    function flap() external returns (uint256);
    function cage() external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/mip21/RwaInputConduitAbstract.sol
// SPDX-FileCopyrightText: © 2022 Dai Foundation <www.daifoundation.org>

interface RwaInputConduitBaseAbstract {
    function dai() external view returns (address);
    function to() external view returns (address);
    function push() external;
}

// https://github.com/makerdao/mip21-toolkit/blob/master/src/conduits/RwaInputConduit.sol
interface RwaInputConduitAbstract is RwaInputConduitBaseAbstract {
    function gov() external view returns (address);
}

// https://github.com/makerdao/mip21-toolkit/blob/master/src/conduits/RwaInputConduit2.sol
interface RwaInputConduit2Abstract is RwaInputConduitBaseAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function may(address) external view returns (uint256);
    function mate(address) external;
    function hate(address) external;
}

// https://github.com/makerdao/mip21-toolkit/blob/master/src/conduits/RwaInputConduit3.sol
interface RwaInputConduit3Abstract is RwaInputConduitBaseAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function may(address) external view returns (uint256);
    function mate(address) external;
    function hate(address) external;
    function psm() external view returns (address);
    function gem() external view returns (address);
    function quitTo() external view returns (address);
    function file(bytes32, address) external;
    function push(uint) external;
    function quit() external;
    function quit(uint) external;
    function yank(address, address, uint256) external;
    function expectedDaiWad(uint256) external view returns (uint256);
    function requiredGemAmt(uint256) external view returns (uint256);
}

// lib/dss-test/lib/dss-interfaces/src/dss/mip21/RwaJarAbstract.sol
// SPDX-FileCopyrightText: © 2022 Dai Foundation <www.daifoundation.org>

// https://github.com/makerdao/mip21-toolkit/blob/master/src/jars/RwaJar.sol
interface RwaJarAbstract {
    function daiJoin() external view returns(address);
    function dai() external view returns(address);
    function chainlog() external view returns(address);
    function void() external;
    function toss(uint256) external;
}

// lib/dss-test/lib/dss-interfaces/src/dss/mip21/RwaLiquidationOracleAbstract.sol
// SPDX-FileCopyrightText: © 2022 Dai Foundation <www.daifoundation.org>

// https://github.com/makerdao/mip21-toolkit/blob/master/src/oracles/RwaLiquidationOracle.sol
interface RwaLiquidationOracleAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function vat() external view returns (address);
    function vow() external view returns (address);
    function ilks(bytes32) external view returns(string memory, address, uint48, uint48);
    function file(bytes32, address) external;
    function init(bytes32, uint256, string calldata, uint48) external;
    function bump(bytes32, uint256) external;
    function tell(bytes32) external;
    function cure(bytes32) external;
    function cull(bytes32, address) external;
    function good(bytes32) external view returns (bool);
}

// lib/dss-test/lib/dss-interfaces/src/dss/mip21/RwaOutputConduitAbstract.sol
// SPDX-FileCopyrightText: © 2022 Dai Foundation <www.daifoundation.org>

interface RwaOutputConduitBaseAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function can(address) external view returns (uint256);
    function hope(address) external;
    function nope(address) external;
    function dai() external view returns (address);
    function to() external view returns (address);
    function pick(address) external;
    function push() external;
}

// https://github.com/makerdao/mip21-toolkit/blob/master/src/conduits/RwaOutputConduit.sol
interface RwaOutputConduitAbstract is RwaOutputConduitBaseAbstract {
    function gov() external view returns (address);
    function bud(address) external view returns (uint256);
    function kiss(address) external;
    function diss(address) external;
}

// https://github.com/makerdao/mip21-toolkit/blob/master/src/conduits/RwaOutputConduit2.sol
interface RwaOutputConduit2Abstract is RwaOutputConduitBaseAbstract {
    function may(address) external view returns (uint256);
    function mate(address) external;
    function hate(address) external;
}

// https://github.com/makerdao/mip21-toolkit/blob/master/src/conduits/RwaOutputConduit3.sol
interface RwaOutputConduit3Abstract is RwaOutputConduitBaseAbstract {
    function bud(address) external view returns (uint256);
    function kiss(address) external;
    function diss(address) external;
    function may(address) external view returns (uint256);
    function mate(address) external;
    function hate(address) external;
    function psm() external view returns (address);
    function gem() external view returns (address);
    function quitTo() external view returns (address);
    function file(bytes32, address) external;
    function push(uint) external;
    function quit() external;
    function quit(uint) external;
    function yank(address, address, uint256) external;
    function expectedGemAmt(uint256) external view returns (uint256);
    function requiredDaiWad(uint256) external view returns (uint256);
}

// lib/dss-test/lib/dss-interfaces/src/dss/mip21/RwaUrnAbstract.sol
// SPDX-FileCopyrightText: © 2022 Dai Foundation <www.daifoundation.org>

// https://github.com/makerdao/mip21-toolkit/blob/master/src/urns/RwaUrn.sol
// https://github.com/makerdao/mip21-toolkit/blob/master/src/urns/RwaUrn2.sol
interface RwaUrnAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function can(address) external view returns (uint256);
    function hope(address) external;
    function nope(address) external;
    function vat() external view returns (address);
    function jug() external view returns (address);
    function gemJoin() external view returns (address);
    function daiJoin() external view returns (address);
    function outputConduit() external view returns (address);
    function file(bytes32, address) external;
    function lock(uint256) external;
    function draw(uint256) external;
    function wipe(uint256) external;
    function free(uint256) external;
    function quit() external;
}

// lib/dss-test/lib/dss-interfaces/src/sai/GemPitAbstract.sol

// https://github.com/makerdao/sai/blob/master/src/pit.sol
interface GemPitAbstract {
    function burn(address) external;
}

// lib/dss-test/lib/dss-interfaces/src/sai/SaiMomAbstract.sol

// https://github.com/makerdao/sai/blob/master/src/mom.sol
interface SaiMomAbstract {
    function tub() external view returns (address);
    function tap() external view returns (address);
    function vox() external view returns (address);
    function setCap(uint256) external;
    function setMat(uint256) external;
    function setTax(uint256) external;
    function setFee(uint256) external;
    function setAxe(uint256) external;
    function setTubGap(uint256) external;
    function setPip(address) external;
    function setPep(address) external;
    function setVox(address) external;
    function setTapGap(uint256) external;
    function setWay(uint256) external;
    function setHow(uint256) external;
    function authority() external view returns (address);
    function owner() external view returns (address);
    function setOwner(address) external;
    function setAuthority(address) external;
}

// lib/dss-test/lib/dss-interfaces/src/sai/SaiTapAbstract.sol

// https://github.com/makerdao/sai/blob/master/src/tap.sol
interface SaiTapAbstract {
    function sai() external view returns (address);
    function sin() external view returns (address);
    function skr() external view returns (address);
    function vox() external view returns (address);
    function tub() external view returns (address);
    function gap() external view returns (uint256);
    function off() external view returns (bool);
    function fix() external view returns (uint256);
    function joy() external view returns (uint256);
    function woe() external view returns (uint256);
    function fog() external view returns (uint256);
    function mold(bytes32, uint256) external;
    function heal() external;
    function s2s() external returns (uint256);
    function bid(uint256) external returns (uint256);
    function ask(uint256) external returns (uint256);
    function bust(uint256) external;
    function boom(uint256) external;
    function cage(uint256) external;
    function cash(uint256) external;
    function mock(uint256) external;
    function vent() external;
    function authority() external view returns (address);
    function owner() external view returns (address);
    function setOwner(address) external;
    function setAuthority(address) external;
}

// lib/dss-test/lib/dss-interfaces/src/sai/SaiTopAbstract.sol

// https://github.com/makerdao/sai/blob/master/src/top.sol
interface SaiTopAbstract {
    function vox() external view returns (address);
    function tub() external view returns (address);
    function tap() external view returns (address);
    function sai() external view returns (address);
    function sin() external view returns (address);
    function skr() external view returns (address);
    function gem() external view returns (address);
    function fix() external view returns (uint256);
    function fit() external view returns (uint256);
    function caged() external view returns (uint256);
    function cooldown() external view returns (uint256);
    function era() external view returns (uint256);
    function cage() external;
    function flow() external;
    function setCooldown(uint256) external;
    function authority() external view returns (address);
    function owner() external view returns (address);
    function setOwner(address) external;
    function setAuthority(address) external;
}

// lib/dss-test/lib/dss-interfaces/src/sai/SaiTubAbstract.sol

// https://github.com/makerdao/sai/blob/master/src/tub.sol
interface SaiTubAbstract {
    function sai() external view returns (address);
    function sin() external view returns (address);
    function skr() external view returns (address);
    function gem() external view returns (address);
    function gov() external view returns (address);
    function vox() external view returns (address);
    function pip() external view returns (address);
    function pep() external view returns (address);
    function tap() external view returns (address);
    function pit() external view returns (address);
    function axe() external view returns (uint256);
    function cap() external view returns (uint256);
    function mat() external view returns (uint256);
    function tax() external view returns (uint256);
    function fee() external view returns (uint256);
    function gap() external view returns (uint256);
    function off() external view returns (bool);
    function out() external view returns (bool);
    function fit() external view returns (uint256);
    function rho() external view returns (uint256);
    function rum() external view returns (uint256);
    function cupi() external view returns (uint256);
    function cups(bytes32) external view returns (address, uint256, uint256, uint256);
    function lad(bytes32) external view returns (address);
    function ink(bytes32) external view returns (address);
    function tab(bytes32) external view returns (uint256);
    function rap(bytes32) external returns (uint256);
    function din() external returns (uint256);
    function air() external view returns (uint256);
    function pie() external view returns (uint256);
    function era() external view returns (uint256);
    function mold(bytes32, uint256) external;
    function setPip(address) external;
    function setPep(address) external;
    function setVox(address) external;
    function turn(address) external;
    function per() external view returns (uint256);
    function ask(uint256) external view returns (uint256);
    function bid(uint256) external view returns (uint256);
    function join(uint256) external;
    function exit(uint256) external;
    function chi() external returns (uint256);
    function rhi() external returns (uint256);
    function drip() external;
    function tag() external view returns (uint256);
    function safe(bytes32) external returns (bool);
    function open() external returns (bytes32);
    function give(bytes32, address) external;
    function lock(bytes32, uint256) external;
    function free(bytes32, uint256) external;
    function draw(bytes32, uint256) external;
    function wipe(bytes32, uint256) external;
    function shut(bytes32) external;
    function bite(bytes32) external;
    function cage(uint256, uint256) external;
    function flow() external;
    function authority() external view returns (address);
    function owner() external view returns (address);
    function setOwner(address) external;
    function setAuthority(address) external;
}

// lib/dss-test/lib/dss-interfaces/src/sai/SaiVoxAbstract.sol

// https://github.com/makerdao/sai/blob/master/src/vox.sol
interface SaiVoxAbstract {
    function fix() external view returns (uint256);
    function how() external view returns (uint256);
    function tau() external view returns (uint256);
    function era() external view returns (uint256);
    function mold(bytes32, uint256) external;
    function par() external returns (uint256);
    function way() external returns (uint256);
    function tell(uint256) external;
    function tune(uint256) external;
    function prod() external;
    function authority() external view returns (address);
    function owner() external view returns (address);
    function setOwner(address) external;
    function setAuthority(address) external;
}

// lib/dss-test/lib/dss-interfaces/src/utils/WardsAbstract.sol

interface WardsAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
}

// lib/dss-test/lib/forge-std/src/Vm.sol

// Cheatcodes are marked as view/pure/none using the following rules:
// 0. A call's observable behaviour includes its return value, logs, reverts and state writes,
// 1. If you can influence a later call's observable behaviour, you're neither `view` nor `pure (you are modifying some state be it the EVM, interpreter, filesystem, etc),
// 2. Otherwise if you can be influenced by an earlier call, or if reading some state, you're `view`,
// 3. Otherwise you're `pure`.

// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may
// result in Script simulations differing from on-chain execution. It is recommended to only use
// these cheats in scripts.
interface VmSafe {
    //  ======== Types ========
    enum CallerMode {
        None,
        Broadcast,
        RecurrentBroadcast,
        Prank,
        RecurrentPrank
    }

    enum AccountAccessKind {
        Call,
        DelegateCall,
        CallCode,
        StaticCall,
        Create,
        SelfDestruct,
        Resume,
        Balance,
        Extcodesize,
        Extcodehash,
        Extcodecopy
    }

    struct Log {
        bytes32[] topics;
        bytes data;
        address emitter;
    }

    struct Rpc {
        string key;
        string url;
    }

    struct EthGetLogs {
        address emitter;
        bytes32[] topics;
        bytes data;
        bytes32 blockHash;
        uint64 blockNumber;
        bytes32 transactionHash;
        uint64 transactionIndex;
        uint256 logIndex;
        bool removed;
    }

    struct DirEntry {
        string errorMessage;
        string path;
        uint64 depth;
        bool isDir;
        bool isSymlink;
    }

    struct FsMetadata {
        bool isDir;
        bool isSymlink;
        uint256 length;
        bool readOnly;
        uint256 modified;
        uint256 accessed;
        uint256 created;
    }

    struct Wallet {
        address addr;
        uint256 publicKeyX;
        uint256 publicKeyY;
        uint256 privateKey;
    }

    struct FfiResult {
        int32 exitCode;
        bytes stdout;
        bytes stderr;
    }

    struct ChainInfo {
        uint256 forkId;
        uint256 chainId;
    }

    struct AccountAccess {
        ChainInfo chainInfo;
        AccountAccessKind kind;
        address account;
        address accessor;
        bool initialized;
        uint256 oldBalance;
        uint256 newBalance;
        bytes deployedCode;
        uint256 value;
        bytes data;
        bool reverted;
        StorageAccess[] storageAccesses;
    }

    struct StorageAccess {
        address account;
        bytes32 slot;
        bool isWrite;
        bytes32 previousValue;
        bytes32 newValue;
        bool reverted;
    }

    // ======== EVM  ========

    // Gets the address for a given private key
    function addr(uint256 privateKey) external pure returns (address keyAddr);

    // Gets the nonce of an account.
    // See `getNonce(Wallet memory wallet)` for an alternative way to manage users and get their nonces.
    function getNonce(address account) external view returns (uint64 nonce);

    // Loads a storage slot from an address
    function load(address target, bytes32 slot) external view returns (bytes32 data);

    // Signs data
    function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);

    // -------- Record Storage --------
    // Records all storage reads and writes
    function record() external;

    // Gets all accessed reads and write slot from a `vm.record` session, for a given address
    function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);

    // Record all account accesses as part of CREATE, CALL or SELFDESTRUCT opcodes in order,
    // along with the context of the calls.
    function startStateDiffRecording() external;

    // Returns an ordered array of all account accesses from a `vm.startStateDiffRecording` session.
    function stopAndReturnStateDiff() external returns (AccountAccess[] memory accountAccesses);

    // -------- Recording Map Writes --------

    // Starts recording all map SSTOREs for later retrieval.
    function startMappingRecording() external;

    // Stops recording all map SSTOREs for later retrieval and clears the recorded data.
    function stopMappingRecording() external;

    // Gets the number of elements in the mapping at the given slot, for a given address.
    function getMappingLength(address target, bytes32 mappingSlot) external returns (uint256 length);

    // Gets the elements at index idx of the mapping at the given slot, for a given address. The
    // index must be less than the length of the mapping (i.e. the number of keys in the mapping).
    function getMappingSlotAt(address target, bytes32 mappingSlot, uint256 idx) external returns (bytes32 value);

    // Gets the map key and parent of a mapping at a given slot, for a given address.
    function getMappingKeyAndParentOf(address target, bytes32 elementSlot)
        external
        returns (bool found, bytes32 key, bytes32 parent);

    // -------- Record Logs --------
    // Record all the transaction logs
    function recordLogs() external;

    // Gets all the recorded logs
    function getRecordedLogs() external returns (Log[] memory logs);

    // -------- Gas Metering --------
    // It's recommend to use the `noGasMetering` modifier included with forge-std, instead of
    // using these functions directly.

    // Pauses gas metering (i.e. gas usage is not counted). Noop if already paused.
    function pauseGasMetering() external;

    // Resumes gas metering (i.e. gas usage is counted again). Noop if already on.
    function resumeGasMetering() external;

    // -------- RPC Methods --------

    /// Gets all the logs according to specified filter.
    function eth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] calldata topics)
        external
        returns (EthGetLogs[] memory logs);

    // Performs an Ethereum JSON-RPC request to the current fork URL.
    function rpc(string calldata method, string calldata params) external returns (bytes memory data);

    // ======== Test Configuration ========

    // If the condition is false, discard this run's fuzz inputs and generate new ones.
    function assume(bool condition) external pure;

    // Writes a breakpoint to jump to in the debugger
    function breakpoint(string calldata char) external;

    // Writes a conditional breakpoint to jump to in the debugger
    function breakpoint(string calldata char, bool value) external;

    // Returns the RPC url for the given alias
    function rpcUrl(string calldata rpcAlias) external view returns (string memory json);

    // Returns all rpc urls and their aliases `[alias, url][]`
    function rpcUrls() external view returns (string[2][] memory urls);

    // Returns all rpc urls and their aliases as structs.
    function rpcUrlStructs() external view returns (Rpc[] memory urls);

    // Suspends execution of the main thread for `duration` milliseconds
    function sleep(uint256 duration) external;

    // ======== OS and Filesystem ========

    // -------- Metadata --------

    // Returns true if the given path points to an existing entity, else returns false
    function exists(string calldata path) external returns (bool result);

    // Given a path, query the file system to get information about a file, directory, etc.
    function fsMetadata(string calldata path) external view returns (FsMetadata memory metadata);

    // Returns true if the path exists on disk and is pointing at a directory, else returns false
    function isDir(string calldata path) external returns (bool result);

    // Returns true if the path exists on disk and is pointing at a regular file, else returns false
    function isFile(string calldata path) external returns (bool result);

    // Get the path of the current project root.
    function projectRoot() external view returns (string memory path);

    // Returns the time since unix epoch in milliseconds
    function unixTime() external returns (uint256 milliseconds);

    // -------- Reading and writing --------

    // Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.
    // `path` is relative to the project root.
    function closeFile(string calldata path) external;

    // Copies the contents of one file to another. This function will **overwrite** the contents of `to`.
    // On success, the total number of bytes copied is returned and it is equal to the length of the `to` file as reported by `metadata`.
    // Both `from` and `to` are relative to the project root.
    function copyFile(string calldata from, string calldata to) external returns (uint64 copied);

    // Creates a new, empty directory at the provided path.
    // This cheatcode will revert in the following situations, but is not limited to just these cases:
    // - User lacks permissions to modify `path`.
    // - A parent of the given path doesn't exist and `recursive` is false.
    // - `path` already exists and `recursive` is false.
    // `path` is relative to the project root.
    function createDir(string calldata path, bool recursive) external;

    // Reads the directory at the given path recursively, up to `max_depth`.
    // `max_depth` defaults to 1, meaning only the direct children of the given directory will be returned.
    // Follows symbolic links if `follow_links` is true.
    function readDir(string calldata path) external view returns (DirEntry[] memory entries);
    function readDir(string calldata path, uint64 maxDepth) external view returns (DirEntry[] memory entries);
    function readDir(string calldata path, uint64 maxDepth, bool followLinks)
        external
        view
        returns (DirEntry[] memory entries);

    // Reads the entire content of file to string. `path` is relative to the project root.
    function readFile(string calldata path) external view returns (string memory data);

    // Reads the entire content of file as binary. `path` is relative to the project root.
    function readFileBinary(string calldata path) external view returns (bytes memory data);

    // Reads next line of file to string.
    function readLine(string calldata path) external view returns (string memory line);

    // Reads a symbolic link, returning the path that the link points to.
    // This cheatcode will revert in the following situations, but is not limited to just these cases:
    // - `path` is not a symbolic link.
    // - `path` does not exist.
    function readLink(string calldata linkPath) external view returns (string memory targetPath);

    // Removes a directory at the provided path.
    // This cheatcode will revert in the following situations, but is not limited to just these cases:
    // - `path` doesn't exist.
    // - `path` isn't a directory.
    // - User lacks permissions to modify `path`.
    // - The directory is not empty and `recursive` is false.
    // `path` is relative to the project root.
    function removeDir(string calldata path, bool recursive) external;

    // Removes a file from the filesystem.
    // This cheatcode will revert in the following situations, but is not limited to just these cases:
    // - `path` points to a directory.
    // - The file doesn't exist.
    // - The user lacks permissions to remove the file.
    // `path` is relative to the project root.
    function removeFile(string calldata path) external;

    // Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.
    // `path` is relative to the project root.
    function writeFile(string calldata path, string calldata data) external;

    // Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does.
    // `path` is relative to the project root.
    function writeFileBinary(string calldata path, bytes calldata data) external;

    // Writes line to file, creating a file if it does not exist.
    // `path` is relative to the project root.
    function writeLine(string calldata path, string calldata data) external;

    // -------- Foreign Function Interface --------

    // Performs a foreign function call via the terminal
    function ffi(string[] calldata commandInput) external returns (bytes memory result);

    // Performs a foreign function call via terminal and returns the exit code, stdout, and stderr
    function tryFfi(string[] calldata commandInput) external returns (FfiResult memory result);

    // ======== Environment Variables ========

    // Sets environment variables
    function setEnv(string calldata name, string calldata value) external;

    // Reads environment variables, (name) => (value)
    function envBool(string calldata name) external view returns (bool value);
    function envUint(string calldata name) external view returns (uint256 value);
    function envInt(string calldata name) external view returns (int256 value);
    function envAddress(string calldata name) external view returns (address value);
    function envBytes32(string calldata name) external view returns (bytes32 value);
    function envString(string calldata name) external view returns (string memory value);
    function envBytes(string calldata name) external view returns (bytes memory value);

    // Reads environment variables as arrays
    function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value);
    function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value);
    function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value);
    function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value);
    function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value);
    function envString(string calldata name, string calldata delim) external view returns (string[] memory value);
    function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value);

    // Read environment variables with default value
    function envOr(string calldata name, bool defaultValue) external returns (bool value);
    function envOr(string calldata name, uint256 defaultValue) external returns (uint256 value);
    function envOr(string calldata name, int256 defaultValue) external returns (int256 value);
    function envOr(string calldata name, address defaultValue) external returns (address value);
    function envOr(string calldata name, bytes32 defaultValue) external returns (bytes32 value);
    function envOr(string calldata name, string calldata defaultValue) external returns (string memory value);
    function envOr(string calldata name, bytes calldata defaultValue) external returns (bytes memory value);

    // Read environment variables as arrays with default value
    function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue)
        external
        returns (bool[] memory value);
    function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue)
        external
        returns (uint256[] memory value);
    function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue)
        external
        returns (int256[] memory value);
    function envOr(string calldata name, string calldata delim, address[] calldata defaultValue)
        external
        returns (address[] memory value);
    function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue)
        external
        returns (bytes32[] memory value);
    function envOr(string calldata name, string calldata delim, string[] calldata defaultValue)
        external
        returns (string[] memory value);
    function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue)
        external
        returns (bytes[] memory value);

    // ======== User Management ========

    // Derives a private key from the name, labels the account with that name, and returns the wallet
    function createWallet(string calldata walletLabel) external returns (Wallet memory wallet);

    // Generates a wallet from the private key and returns the wallet
    function createWallet(uint256 privateKey) external returns (Wallet memory wallet);

    // Generates a wallet from the private key, labels the account with that name, and returns the wallet
    function createWallet(uint256 privateKey, string calldata walletLabel) external returns (Wallet memory wallet);

    // Gets the label for the specified address
    function getLabel(address account) external returns (string memory currentLabel);

    // Get nonce for a Wallet.
    // See `getNonce(address account)` for an alternative way to get a nonce.
    function getNonce(Wallet calldata wallet) external returns (uint64 nonce);

    // Labels an address in call traces
    function label(address account, string calldata newLabel) external;

    // Signs data, (Wallet, digest) => (v, r, s)
    function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s);

    // ======== Scripts ========

    // -------- Broadcasting Transactions --------

    // Using the address that calls the test contract, has the next call (at this call depth only) create a transaction that can later be signed and sent onchain
    function broadcast() external;

    // Has the next call (at this call depth only) create a transaction with the address provided as the sender that can later be signed and sent onchain
    function broadcast(address signer) external;

    // Has the next call (at this call depth only) create a transaction with the private key provided as the sender that can later be signed and sent onchain
    function broadcast(uint256 privateKey) external;

    // Using the address that calls the test contract, has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain
    function startBroadcast() external;

    // Has all subsequent calls (at this call depth only) create transactions with the address provided that can later be signed and sent onchain
    function startBroadcast(address signer) external;

    // Has all subsequent calls (at this call depth only) create transactions with the private key provided that can later be signed and sent onchain
    function startBroadcast(uint256 privateKey) external;

    // Stops collecting onchain transactions
    function stopBroadcast() external;

    // -------- Key Management --------

    // Derive a private key from a provided mnenomic string (or mnenomic file path) at the derivation path m/44'/60'/0'/0/{index}
    function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey);

    // Derive a private key from a provided mnenomic string (or mnenomic file path) at {derivationPath}{index}
    function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index)
        external
        pure
        returns (uint256 privateKey);

    // Adds a private key to the local forge wallet and returns the address
    function rememberKey(uint256 privateKey) external returns (address keyAddr);

    // ======== Utilities ========

    // Convert values to a string
    function toString(address value) external pure returns (string memory stringifiedValue);
    function toString(bytes calldata value) external pure returns (string memory stringifiedValue);
    function toString(bytes32 value) external pure returns (string memory stringifiedValue);
    function toString(bool value) external pure returns (string memory stringifiedValue);
    function toString(uint256 value) external pure returns (string memory stringifiedValue);
    function toString(int256 value) external pure returns (string memory stringifiedValue);

    // Convert values from a string
    function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue);
    function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue);
    function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue);
    function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue);
    function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue);
    function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue);

    // Gets the creation bytecode from an artifact file. Takes in the relative path to the json file
    function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode);

    // Gets the deployed bytecode from an artifact file. Takes in the relative path to the json file
    function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode);

    // Compute the address a contract will be deployed at for a given deployer address and nonce.
    function computeCreateAddress(address deployer, uint256 nonce) external pure returns (address);

    // Compute the address of a contract created with CREATE2 using the given CREATE2 deployer.
    function computeCreate2Address(bytes32 salt, bytes32 initCodeHash, address deployer)
        external
        pure
        returns (address);

    // Compute the address of a contract created with CREATE2 using foundry's default CREATE2
    // deployer: 0x4e59b44847b379578588920cA78FbF26c0B4956C, https://github.com/Arachnid/deterministic-deployment-proxy
    function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) external pure returns (address);

    // ======== JSON Parsing and Manipulation ========

    // -------- Reading --------

    // NOTE: Please read https://book.getfoundry.sh/cheatcodes/parse-json to understand the
    // limitations and caveats of the JSON parsing cheats.

    // Checks if a key exists in a JSON object.
    function keyExists(string calldata json, string calldata key) external view returns (bool);

    // Given a string of JSON, return it as ABI-encoded
    function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData);
    function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData);

    // The following parseJson cheatcodes will do type coercion, for the type that they indicate.
    // For example, parseJsonUint will coerce all values to a uint256. That includes stringified numbers '12'
    // and hex numbers '0xEF'.
    // Type coercion works ONLY for discrete values or arrays. That means that the key must return a value or array, not
    // a JSON object.
    function parseJsonUint(string calldata json, string calldata key) external pure returns (uint256);
    function parseJsonUintArray(string calldata json, string calldata key) external pure returns (uint256[] memory);
    function parseJsonInt(string calldata json, string calldata key) external pure returns (int256);
    function parseJsonIntArray(string calldata json, string calldata key) external pure returns (int256[] memory);
    function parseJsonBool(string calldata json, string calldata key) external pure returns (bool);
    function parseJsonBoolArray(string calldata json, string calldata key) external pure returns (bool[] memory);
    function parseJsonAddress(string calldata json, string calldata key) external pure returns (address);
    function parseJsonAddressArray(string calldata json, string calldata key)
        external
        pure
        returns (address[] memory);
    function parseJsonString(string calldata json, string calldata key) external pure returns (string memory);
    function parseJsonStringArray(string calldata json, string calldata key) external pure returns (string[] memory);
    function parseJsonBytes(string calldata json, string calldata key) external pure returns (bytes memory);
    function parseJsonBytesArray(string calldata json, string calldata key) external pure returns (bytes[] memory);
    function parseJsonBytes32(string calldata json, string calldata key) external pure returns (bytes32);
    function parseJsonBytes32Array(string calldata json, string calldata key)
        external
        pure
        returns (bytes32[] memory);

    // Returns array of keys for a JSON object
    function parseJsonKeys(string calldata json, string calldata key) external pure returns (string[] memory keys);

    // -------- Writing --------

    // NOTE: Please read https://book.getfoundry.sh/cheatcodes/serialize-json to understand how
    // to use the serialization cheats.

    // Serialize a key and value to a JSON object stored in-memory that can be later written to a file
    // It returns the stringified version of the specific JSON file up to that moment.
    function serializeJson(string calldata objectKey, string calldata value) external returns (string memory json);
    function serializeBool(string calldata objectKey, string calldata valueKey, bool value)
        external
        returns (string memory json);
    function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value)
        external
        returns (string memory json);
    function serializeInt(string calldata objectKey, string calldata valueKey, int256 value)
        external
        returns (string memory json);
    function serializeAddress(string calldata objectKey, string calldata valueKey, address value)
        external
        returns (string memory json);
    function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value)
        external
        returns (string memory json);
    function serializeString(string calldata objectKey, string calldata valueKey, string calldata value)
        external
        returns (string memory json);
    function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value)
        external
        returns (string memory json);

    function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values)
        external
        returns (string memory json);
    function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values)
        external
        returns (string memory json);
    function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values)
        external
        returns (string memory json);
    function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values)
        external
        returns (string memory json);
    function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values)
        external
        returns (string memory json);
    function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values)
        external
        returns (string memory json);
    function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values)
        external
        returns (string memory json);

    // NOTE: Please read https://book.getfoundry.sh/cheatcodes/write-json to understand how
    // to use the JSON writing cheats.

    // Write a serialized JSON object to a file. If the file exists, it will be overwritten.
    function writeJson(string calldata json, string calldata path) external;

    // Write a serialized JSON object to an **existing** JSON file, replacing a value with key = <value_key>
    // This is useful to replace a specific value of a JSON file, without having to parse the entire thing
    function writeJson(string calldata json, string calldata path, string calldata valueKey) external;
}

// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used
// in tests, but it is not recommended to use these cheats in scripts.
interface Vm is VmSafe {
    // ======== EVM  ========

    // -------- Block and Transaction Properties --------

    // Sets block.chainid
    function chainId(uint256 newChainId) external;

    // Sets block.coinbase
    function coinbase(address newCoinbase) external;

    // Sets block.difficulty
    // Not available on EVM versions from Paris onwards. Use `prevrandao` instead.
    // If used on unsupported EVM versions it will revert.
    function difficulty(uint256 newDifficulty) external;

    // Sets block.basefee
    function fee(uint256 newBasefee) external;

    // Sets block.prevrandao
    // Not available on EVM versions before Paris. Use `difficulty` instead.
    // If used on unsupported EVM versions it will revert.
    function prevrandao(bytes32 newPrevrandao) external;

    // Sets block.height
    function roll(uint256 newHeight) external;

    // Sets tx.gasprice
    function txGasPrice(uint256 newGasPrice) external;

    // Sets block.timestamp
    function warp(uint256 newTimestamp) external;

    // -------- Account State --------

    // Sets an address' balance
    function deal(address account, uint256 newBalance) external;

    // Sets an address' code
    function etch(address target, bytes calldata newRuntimeBytecode) external;

    // Load a genesis JSON file's `allocs` into the in-memory state.
    function loadAllocs(string calldata pathToAllocsJson) external;

    // Resets the nonce of an account to 0 for EOAs and 1 for contract accounts
    function resetNonce(address account) external;

    // Sets the nonce of an account; must be higher than the current nonce of the account
    function setNonce(address account, uint64 newNonce) external;

    // Sets the nonce of an account to an arbitrary value
    function setNonceUnsafe(address account, uint64 newNonce) external;

    // Stores a value to an address' storage slot.
    function store(address target, bytes32 slot, bytes32 value) external;

    // -------- Call Manipulation --------
    // --- Mocks ---

    // Clears all mocked calls
    function clearMockedCalls() external;

    // Mocks a call to an address, returning specified data.
    // Calldata can either be strict or a partial match, e.g. if you only
    // pass a Solidity selector to the expected calldata, then the entire Solidity
    // function will be mocked.
    function mockCall(address callee, bytes calldata data, bytes calldata returnData) external;

    // Mocks a call to an address with a specific msg.value, returning specified data.
    // Calldata match takes precedence over msg.value in case of ambiguity.
    function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external;

    // Reverts a call to an address with specified revert data.
    function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external;

    // Reverts a call to an address with a specific msg.value, with specified revert data.
    function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData)
        external;

    // --- Impersonation (pranks) ---

    // Sets the *next* call's msg.sender to be the input address
    function prank(address msgSender) external;

    // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called
    function startPrank(address msgSender) external;

    // Sets the *next* call's msg.sender to be the input address, and the tx.origin to be the second input
    function prank(address msgSender, address txOrigin) external;

    // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called, and the tx.origin to be the second input
    function startPrank(address msgSender, address txOrigin) external;

    // Resets subsequent calls' msg.sender to be `address(this)`
    function stopPrank() external;

    // Reads the current `msg.sender` and `tx.origin` from state and reports if there is any active caller modification
    function readCallers() external returns (CallerMode callerMode, address msgSender, address txOrigin);

    // -------- State Snapshots --------

    // Snapshot the current state of the evm.
    // Returns the id of the snapshot that was created.
    // To revert a snapshot use `revertTo`
    function snapshot() external returns (uint256 snapshotId);

    // Revert the state of the EVM to a previous snapshot
    // Takes the snapshot id to revert to.
    // Returns true if the revert succeeded, false otherwise.
    //
    // This does not automatically delete the snapshot. To delete the snapshot use `deleteSnapshot` or `revertToAndDelete`
    function revertTo(uint256 snapshotId) external returns (bool success);

    // Deletes the snapshot.
    // Returns true if the snapshot existed, false otherwise.
    //
    // This does not revert to the state of the snapshot, only deletes it.
    function deleteSnapshot(uint256 snapshotId) external returns (bool success);

    // Deletes all snapshots.
    function deleteSnapshots() external;

    // Revert the state of the EVM to a previous snapshot
    // Takes the snapshot id to revert to.
    //
    // This also deletes the snapshot after reverting to its state.
    function revertToAndDelete(uint256 snapshotId) external returns (bool success);

    // -------- Forking --------
    // --- Creation and Selection ---

    // Returns the identifier of the currently active fork. Reverts if no fork is currently active.
    function activeFork() external view returns (uint256 forkId);

    // Creates a new fork with the given endpoint and block and returns the identifier of the fork
    function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);

    // Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork
    function createFork(string calldata urlOrAlias) external returns (uint256 forkId);

    // Creates a new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before the transaction,
    // and returns the identifier of the fork
    function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);

    // Creates and also selects a new fork with the given endpoint and block and returns the identifier of the fork
    function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);

    // Creates and also selects new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before
    // the transaction, returns the identifier of the fork
    function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);

    // Creates and also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork
    function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId);

    // Updates the currently active fork to given block number
    // This is similar to `roll` but for the currently active fork
    function rollFork(uint256 blockNumber) external;

    // Updates the currently active fork to given transaction
    // this will `rollFork` with the number of the block the transaction was mined in and replays all transaction mined before it in the block
    function rollFork(bytes32 txHash) external;

    // Updates the given fork to given block number
    function rollFork(uint256 forkId, uint256 blockNumber) external;

    // Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block
    function rollFork(uint256 forkId, bytes32 txHash) external;

    // Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.
    function selectFork(uint256 forkId) external;

    // Fetches the given transaction from the active fork and executes it on the current state
    function transact(bytes32 txHash) external;

    // Fetches the given transaction from the given fork and executes it on the current state
    function transact(uint256 forkId, bytes32 txHash) external;

    // --- Behavior ---

    // In forking mode, explicitly grant the given address cheatcode access
    function allowCheatcodes(address account) external;

    // Marks that the account(s) should use persistent storage across fork swaps in a multifork setup
    // Meaning, changes made to the state of this account will be kept when switching forks
    function makePersistent(address account) external;
    function makePersistent(address account0, address account1) external;
    function makePersistent(address account0, address account1, address account2) external;
    function makePersistent(address[] calldata accounts) external;

    // Revokes persistent status from the address, previously added via `makePersistent`
    function revokePersistent(address account) external;
    function revokePersistent(address[] calldata accounts) external;

    // Returns true if the account is marked as persistent
    function isPersistent(address account) external view returns (bool persistent);

    // ======== Test Assertions and Utilities ========

    // Expects a call to an address with the specified calldata.
    // Calldata can either be a strict or a partial match
    function expectCall(address callee, bytes calldata data) external;

    // Expects given number of calls to an address with the specified calldata.
    function expectCall(address callee, bytes calldata data, uint64 count) external;

    // Expects a call to an address with the specified msg.value and calldata
    function expectCall(address callee, uint256 msgValue, bytes calldata data) external;

    // Expects given number of calls to an address with the specified msg.value and calldata
    function expectCall(address callee, uint256 msgValue, bytes calldata data, uint64 count) external;

    // Expect a call to an address with the specified msg.value, gas, and calldata.
    function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external;

    // Expects given number of calls to an address with the specified msg.value, gas, and calldata.
    function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data, uint64 count) external;

    // Expect a call to an address with the specified msg.value and calldata, and a *minimum* amount of gas.
    function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external;

    // Expect given number of calls to an address with the specified msg.value and calldata, and a *minimum* amount of gas.
    function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data, uint64 count)
        external;

    // Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData).
    // Call this function, then emit an event, then call a function. Internally after the call, we check if
    // logs were emitted in the expected order with the expected topics and data (as specified by the booleans).
    function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external;

    // Same as the previous method, but also checks supplied address against emitting contract.
    function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter)
        external;

    // Prepare an expected log with all topic and data checks enabled.
    // Call this function, then emit an event, then call a function. Internally after the call, we check if
    // logs were emitted in the expected order with the expected topics and data.
    function expectEmit() external;

    // Same as the previous method, but also checks supplied address against emitting contract.
    function expectEmit(address emitter) external;

    // Expects an error on next call that exactly matches the revert data.
    function expectRevert(bytes calldata revertData) external;

    // Expects an error on next call that starts with the revert data.
    function expectRevert(bytes4 revertData) external;

    // Expects an error on next call with any revert data.
    function expectRevert() external;

    // Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other
    // memory is written to, the test will fail. Can be called multiple times to add more ranges to the set.
    function expectSafeMemory(uint64 min, uint64 max) external;

    // Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext.
    // If any other memory is written to, the test will fail. Can be called multiple times to add more ranges
    // to the set.
    function expectSafeMemoryCall(uint64 min, uint64 max) external;

    // Marks a test as skipped. Must be called at the top of the test.
    function skip(bool skipTest) external;
}

// src/dependencies/01-usds/UsdsInstance.sol
// SPDX-FileCopyrightText: © 2023 Dai Foundation <www.daifoundation.org>

//
// 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/>.

struct UsdsInstance {
    address usds;
    address usdsImp;
    address usdsJoin;
    address daiUsds;
}

// src/dependencies/02-susds/SUsdsInstance.sol
// SPDX-FileCopyrightText: © 2023 Dai Foundation <www.daifoundation.org>

//
// 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/>.

struct SUsdsInstance {
    address sUsds;
    address sUsdsImp;
}

// src/dependencies/03-sky/SkyInstance.sol
// SPDX-FileCopyrightText: © 2023 Dai Foundation <www.daifoundation.org>

//
// 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/>.

struct SkyInstance {
    address sky;
    address mkrSky;
}

// src/dependencies/05-flapper/SplitterInstance.sol
// SPDX-FileCopyrightText: © 2023 Dai Foundation <www.daifoundation.org>

//
// 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/>.

struct SplitterInstance {
    address splitter;
    address mom;
}

// src/dependencies/06-farm/StakingRewardsInit.sol

//
// 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/>.

struct StakingRewardsInitParams {
    address dist;
}

struct StakingRewardsNominateNewOwnerParams {
    address newOwner;
}

library StakingRewardsInit {
    function init(address rewards, StakingRewardsInitParams memory p) internal {
        StakingRewardsLike_0(rewards).setRewardsDistribution(p.dist);
    }

    /// @dev `StakingRewards` ownership transfer is a 2-step process: nominate + acceptance.
    function nominateNewOwner(address rewards, StakingRewardsNominateNewOwnerParams memory p) internal {
        StakingRewardsLike_0(rewards).nominateNewOwner(p.newOwner);
    }

    /// @dev `StakingRewards` ownership transfer requires the new owner to explicitly accept it.
    function acceptOwnership(address rewards) internal {
        StakingRewardsLike_0(rewards).acceptOwnership();
    }
}

interface StakingRewardsLike_0 {
    function setRewardsDistribution(address _rewardsDistribution) external;

    function acceptOwnership() external;

    function nominateNewOwner(address _owner) external;
}

// src/dependencies/06-farm/VestInit.sol

//
// 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/>.

struct VestCreateParams {
    address usr;
    uint256 tot;
    uint256 bgn;
    uint256 tau;
    uint256 eta;
}

/// @dev Handles vesting stream creation. Assumes `DssVest` parameters are initialized somewhere else.
library VestInit {
    function create(address vest, VestCreateParams memory p) internal returns (uint256 vestId) {
        vestId = DssVestLike(vest).create(
            p.usr,
            p.tot,
            p.bgn,
            p.tau,
            p.eta,
            address(0) // mgr
        );

        DssVestLike(vest).restrict(vestId);
    }
}

interface DssVestLike {
    function create(
        address _usr,
        uint256 _tot,
        uint256 _bgn,
        uint256 _tau,
        uint256 _eta,
        address _mgr
    ) external returns (uint256 id);

    function restrict(uint256 _id) external;
}

// src/dependencies/06-farm/VestedRewardsDistributionInit.sol

//
// 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/>.

struct VestedRewardsDistributionInitParams {
    uint256 vestId;
}

library VestedRewardsDistributionInit {
    function init(address dist, VestedRewardsDistributionInitParams memory p) internal {
        VestedRewardsDistributionLike_0(dist).file("vestId", p.vestId);
    }
}

interface VestedRewardsDistributionLike_0 {
    function file(bytes32 what, uint256 data) external;
}

// src/dependencies/06-farm/phase-1b/Usds01PreFarmingInit.sol

//
// 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/>.

struct Usds01PreFarmingInitParams {
    address usds;
    address rewards;
    bytes32 rewardsKey; // Chainlog key
}

library Usds01PreFarmingInit {
    ChainlogLike_0 internal constant chainlog = ChainlogLike_0(0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F);

    function init(Usds01PreFarmingInitParams memory p) internal {
        require(
            StakingRewardsLike_1(p.rewards).stakingToken() == p.usds,
            "Usds01PreFarmingInit/rewards-staking-token-mismatch"
        );
        require(
            StakingRewardsLike_1(p.rewards).rewardsToken() == address(0),
            "Usds01PreFarmingInit/invalid-rewards-token"
        );
        require(StakingRewardsLike_1(p.rewards).rewardRate() == 0, "Usds01PreFarmingInit/reward-rate-not-zero");
        require(
            StakingRewardsLike_1(p.rewards).rewardsDistribution() == address(0),
            "Usds01PreFarmingInit/rewards-distribution-already-set"
        );
        require(
            StakingRewardsLike_1(p.rewards).owner() == chainlog.getAddress("MCD_PAUSE_PROXY"),
            "Usds01PreFarmingInit/invalid-owner"
        );

        chainlog.setAddress(p.rewardsKey, p.rewards);
    }
}

interface StakingRewardsLike_1 {
    function owner() external view returns (address);

    function rewardRate() external view returns (uint256);

    function rewardsDistribution() external view returns (address);

    function rewardsToken() external view returns (address);

    function stakingToken() external view returns (address);
}

interface ChainlogLike_0 {
    function getAddress(bytes32 key) external view returns (address);

    function setAddress(bytes32 key, address addr) external;
}

// src/dependencies/07-cron/VestedRewardsDistributionJobInit.sol
// SPDX-FileCopyrightText: © 2023 Dai Foundation <www.daifoundation.org>

//
// 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/>.

struct VestedRewardsDistributionJobInitConfig {
    bytes32 jobKey; // Chainlog key
}

struct VestedRewardsDistributionJobDeinitConfig {
    bytes32 jobKey; // Chainlog key
}

struct VestedRewardsDistributionJobSetDistConfig {
    address dist;
    uint256 interval;
}

struct VestedRewardsDistributionJobRemDistConfig {
    address dist;
}

library VestedRewardsDistributionJobInit {
    ChainlogLike_1 internal constant chainlog = ChainlogLike_1(0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F);

    function init(address job, VestedRewardsDistributionJobInitConfig memory cfg) internal {
        SequencerLike sequencer = SequencerLike(chainlog.getAddress("CRON_SEQUENCER"));
        require(
            VestedRewardsDistributionJobLike(job).sequencer() == address(sequencer),
            "VestedRewardsDistributionJobInit/invalid-sequencer"
        );
        sequencer.addJob(job);
        chainlog.setAddress(cfg.jobKey, job);
    }

    function deinit(address job, VestedRewardsDistributionJobDeinitConfig memory cfg) internal {
        SequencerLike sequencer = SequencerLike(chainlog.getAddress("CRON_SEQUENCER"));
        require(
            VestedRewardsDistributionJobLike(job).sequencer() == address(sequencer),
            "VestedRewardsDistributionJobInit/invalid-sequencer"
        );
        sequencer.removeJob(job);
        chainlog.removeAddress(cfg.jobKey);
    }

    function setDist(address job, VestedRewardsDistributionJobSetDistConfig memory cfg) internal {
        VestedRewardsDistributionJobLike(job).set(cfg.dist, cfg.interval);
    }

    function remDist(address job, VestedRewardsDistributionJobRemDistConfig memory cfg) internal {
        VestedRewardsDistributionJobLike(job).rem(cfg.dist);
    }
}

interface VestedRewardsDistributionJobLike {
    function sequencer() external view returns (address);
    function set(address dist, uint256 interval) external;
    function rem(address dist) external;
}

interface ChainlogLike_1 {
    function getAddress(bytes32 key) external view returns (address);
    function removeAddress(bytes32 key) external;
    function setAddress(bytes32 key, address val) external;
}

interface SequencerLike {
    function addJob(address job) external;
    function removeJob(address job) external;
}

// lib/dss-exec-lib/src/DssExecLib.sol

//
// DssExecLib.sol -- MakerDAO Executive Spellcrafting Library
//
// Copyright (C) 2020-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/>.

interface Initializable {
    function init(bytes32) external;
}

interface Authorizable {
    function rely(address) external;
    function deny(address) external;
    function setAuthority(address) external;
}

interface Fileable {
    function file(bytes32, address) external;
    function file(bytes32, uint256) external;
    function file(bytes32, bytes32, uint256) external;
    function file(bytes32, bytes32, address) external;
}

interface Drippable {
    function drip() external returns (uint256);
    function drip(bytes32) external returns (uint256);
}

interface Pricing {
    function poke(bytes32) external;
}

interface ERC20 {
    function decimals() external returns (uint8);
}

interface DssVat {
    function hope(address) external;
    function nope(address) external;
    function ilks(bytes32) external returns (uint256 Art, uint256 rate, uint256 spot, uint256 line, uint256 dust);
    function Line() external view returns (uint256);
    function suck(address, address, uint256) external;
}

interface ClipLike {
    function vat() external returns (address);
    function dog() external returns (address);
    function spotter() external view returns (address);
    function calc() external view returns (address);
    function ilk() external returns (bytes32);
}

interface DogLike {
    function ilks(bytes32) external returns (address clip, uint256 chop, uint256 hole, uint256 dirt);
}

interface JoinLike {
    function vat() external returns (address);
    function ilk() external returns (bytes32);
    function gem() external returns (address);
    function dec() external returns (uint256);
    function join(address, uint256) external;
    function exit(address, uint256) external;
}

// Includes Median and OSM functions
interface OracleLike_0 {
    function src() external view returns (address);
    function lift(address[] calldata) external;
    function drop(address[] calldata) external;
    function setBar(uint256) external;
    function kiss(address) external;
    function diss(address) external;
    function kiss(address[] calldata) external;
    function diss(address[] calldata) external;
    function orb0() external view returns (address);
    function orb1() external view returns (address);
}

interface MomLike {
    function setOsm(bytes32, address) external;
    function setPriceTolerance(address, uint256) external;
}

interface RegistryLike {
    function add(address) external;
    function xlip(bytes32) external view returns (address);
}

// https://github.com/makerdao/dss-chain-log
interface ChainlogLike_2 {
    function setVersion(string calldata) external;
    function setIPFS(string calldata) external;
    function setSha256sum(string calldata) external;
    function getAddress(bytes32) external view returns (address);
    function setAddress(bytes32, address) external;
    function removeAddress(bytes32) external;
}

interface IAMLike {
    function ilks(bytes32) external view returns (uint256,uint256,uint48,uint48,uint48);
    function setIlk(bytes32,uint256,uint256,uint256) external;
    function remIlk(bytes32) external;
    function exec(bytes32) external returns (uint256);
}

interface LerpFactoryLike {
    function newLerp(bytes32 name_, address target_, bytes32 what_, uint256 startTime_, uint256 start_, uint256 end_, uint256 duration_) external returns (address);
    function newIlkLerp(bytes32 name_, address target_, bytes32 ilk_, bytes32 what_, uint256 startTime_, uint256 start_, uint256 end_, uint256 duration_) external returns (address);
}

interface LerpLike {
    function tick() external returns (uint256);
}

interface RwaOracleLike {
    function bump(bytes32 ilk, uint256 val) external;
}

library DssExecLib {

    /*****************/
    /*** Constants ***/
    /*****************/
    address constant public LOG = 0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F;

    uint256 constant internal WAD      = 10 ** 18;
    uint256 constant internal RAY      = 10 ** 27;
    uint256 constant internal RAD      = 10 ** 45;
    uint256 constant internal THOUSAND = 10 ** 3;
    uint256 constant internal MILLION  = 10 ** 6;

    uint256 constant internal BPS_ONE_PCT             = 100;
    uint256 constant internal BPS_ONE_HUNDRED_PCT     = 100 * BPS_ONE_PCT;
    uint256 constant internal RATES_ONE_HUNDRED_PCT   = 1000000021979553151239153027;

    /**********************/
    /*** Math Functions ***/
    /**********************/
    function wdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = (x * WAD + y / 2) / y;
    }
    function rdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = (x * RAY + y / 2) / y;
    }

    /****************************/
    /*** Core Address Helpers ***/
    /****************************/
    function dai()        public view returns (address) { return getChangelogAddress("MCD_DAI"); }
    function mkr()        public view returns (address) { return getChangelogAddress("MCD_GOV"); }
    function vat()        public view returns (address) { return getChangelogAddress("MCD_VAT"); }
    function cat()        public view returns (address) { return getChangelogAddress("MCD_CAT"); }
    function dog()        public view returns (address) { return getChangelogAddress("MCD_DOG"); }
    function jug()        public view returns (address) { return getChangelogAddress("MCD_JUG"); }
    function pot()        public view returns (address) { return getChangelogAddress("MCD_POT"); }
    function vow()        public view returns (address) { return getChangelogAddress("MCD_VOW"); }
    function end()        public view returns (address) { return getChangelogAddress("MCD_END"); }
    function esm()        public view returns (address) { return getChangelogAddress("MCD_ESM"); }
    function reg()        public view returns (address) { return getChangelogAddress("ILK_REGISTRY"); }
    function spotter()    public view returns (address) { return getChangelogAddress("MCD_SPOT"); }
    function flap()       public view returns (address) { return getChangelogAddress("MCD_FLAP"); }
    function flop()       public view returns (address) { return getChangelogAddress("MCD_FLOP"); }
    function osmMom()     public view returns (address) { return getChangelogAddress("OSM_MOM"); }
    function govGuard()   public view returns (address) { return getChangelogAddress("GOV_GUARD"); }
    function flipperMom() public view returns (address) { return getChangelogAddress("FLIPPER_MOM"); }
    function clipperMom() public view returns (address) { return getChangelogAddress("CLIPPER_MOM"); }
    function pauseProxy() public view returns (address) { return getChangelogAddress("MCD_PAUSE_PROXY"); }
    function autoLine()   public view returns (address) { return getChangelogAddress("MCD_IAM_AUTO_LINE"); }
    function daiJoin()    public view returns (address) { return getChangelogAddress("MCD_JOIN_DAI"); }
    function lerpFab()    public view returns (address) { return getChangelogAddress("LERP_FAB"); }

    function clip(bytes32 _ilk) public view returns (address _clip) {
        _clip = RegistryLike(reg()).xlip(_ilk);
    }

    function flip(bytes32 _ilk) public view returns (address _flip) {
        _flip = RegistryLike(reg()).xlip(_ilk);
    }

    function calc(bytes32 _ilk) public view returns (address _calc) {
        _calc = ClipLike(clip(_ilk)).calc();
    }

    function getChangelogAddress(bytes32 _key) public view returns (address) {
        return ChainlogLike_2(LOG).getAddress(_key);
    }

    /****************************/
    /*** Changelog Management ***/
    /****************************/
    /**
        @dev Set an address in the MCD on-chain changelog.
        @param _key Access key for the address (e.g. "MCD_VAT")
        @param _val The address associated with the _key
    */
    function setChangelogAddress(bytes32 _key, address _val) public {
        ChainlogLike_2(LOG).setAddress(_key, _val);
    }

    /**
        @dev Set version in the MCD on-chain changelog.
        @param _version Changelog version (e.g. "1.1.2")
    */
    function setChangelogVersion(string memory _version) public {
        ChainlogLike_2(LOG).setVersion(_version);
    }
    /**
        @dev Set IPFS hash of IPFS changelog in MCD on-chain changelog.
        @param _ipfsHash IPFS hash (e.g. "QmefQMseb3AiTapiAKKexdKHig8wroKuZbmLtPLv4u2YwW")
    */
    function setChangelogIPFS(string memory _ipfsHash) public {
        ChainlogLike_2(LOG).setIPFS(_ipfsHash);
    }
    /**
        @dev Set SHA256 hash in MCD on-chain changelog.
        @param _SHA256Sum SHA256 hash (e.g. "e42dc9d043a57705f3f097099e6b2de4230bca9a020c797508da079f9079e35b")
    */
    function setChangelogSHA256(string memory _SHA256Sum) public {
        ChainlogLike_2(LOG).setSha256sum(_SHA256Sum);
    }

    /**********************/
    /*** Authorizations ***/
    /**********************/
    /**
        @dev Give an address authorization to perform auth actions on the contract.
        @param _base   The address of the contract where the authorization will be set
        @param _ward   Address to be authorized
    */
    function authorize(address _base, address _ward) public {
        Authorizable(_base).rely(_ward);
    }
    /**
        @dev Revoke contract authorization from an address.
        @param _base   The address of the contract where the authorization will be revoked
        @param _ward   Address to be deauthorized
    */
    function deauthorize(address _base, address _ward) public {
        Authorizable(_base).deny(_ward);
    }
    /**
        @dev Give an address authorization to perform auth actions on the contract.
        @param _base   The address of the contract with a `setAuthority` pattern
        @param _authority   Address to be authorized
    */
    function setAuthority(address _base, address _authority) public {
        Authorizable(_base).setAuthority(_authority);
    }
    /**
        @dev Delegate vat authority to the specified address.
        @param _usr Address to be authorized
    */
    function delegateVat(address _usr) public {
        DssVat(vat()).hope(_usr);
    }
    /**
        @dev Revoke vat authority to the specified address.
        @param _usr Address to be deauthorized
    */
    function undelegateVat(address _usr) public {
        DssVat(vat()).nope(_usr);
    }

    /******************************/
    /*** OfficeHours Management ***/
    /******************************/

    /**
        @dev Returns true if a time is within office hours range
        @param _ts           The timestamp to check, usually block.timestamp
        @param _officeHours  true if office hours is enabled.
        @return              true if time is in castable range
    */
    function canCast(uint40 _ts, bool _officeHours) public pure returns (bool) {
        if (_officeHours) {
            uint256 day = (_ts / 1 days + 3) % 7;
            if (day >= 5)                 { return false; }  // Can only be cast on a weekday
            uint256 hour = _ts / 1 hours % 24;
            if (hour < 14 || hour >= 21)  { return false; }  // Outside office hours
        }
        return true;
    }

    /**
        @dev Calculate the next available cast time in epoch seconds
        @param _eta          The scheduled time of the spell plus the pause delay
        @param _ts           The current timestamp, usually block.timestamp
        @param _officeHours  true if office hours is enabled.
        @return castTime     The next available cast timestamp
    */
    function nextCastTime(uint40 _eta, uint40 _ts, bool _officeHours) public pure returns (uint256 castTime) {
        require(_eta != 0);  // "DssExecLib/invalid eta"
        require(_ts  != 0);  // "DssExecLib/invalid ts"
        castTime = _ts > _eta ? _ts : _eta; // Any day at XX:YY

        if (_officeHours) {
            uint256 day    = (castTime / 1 days + 3) % 7;
            uint256 hour   = castTime / 1 hours % 24;
            uint256 minute = castTime / 1 minutes % 60;
            uint256 second = castTime % 60;

            if (day >= 5) {
                castTime += (6 - day) * 1 days;                 // Go to Sunday XX:YY
                castTime += (24 - hour + 14) * 1 hours;         // Go to 14:YY UTC Monday
                castTime -= minute * 1 minutes + second;        // Go to 14:00 UTC
            } else {
                if (hour >= 21) {
                    if (day == 4) castTime += 2 days;           // If Friday, fast forward to Sunday XX:YY
                    castTime += (24 - hour + 14) * 1 hours;     // Go to 14:YY UTC next day
                    castTime -= minute * 1 minutes + second;    // Go to 14:00 UTC
                } else if (hour < 14) {
                    castTime += (14 - hour) * 1 hours;          // Go to 14:YY UTC same day
                    castTime -= minute * 1 minutes + second;    // Go to 14:00 UTC
                }
            }
        }
    }

    /**************************/
    /*** Accumulating Rates ***/
    /**************************/
    /**
        @dev Update rate accumulation for the Dai Savings Rate (DSR).
    */
    function accumulateDSR() public {
        Drippable(pot()).drip();
    }
    /**
        @dev Update rate accumulation for the stability fees of a given collateral type.
        @param _ilk   Collateral type
    */
    function accumulateCollateralStabilityFees(bytes32 _ilk) public {
        Drippable(jug()).drip(_ilk);
    }

    /*********************/
    /*** Price Updates ***/
    /*********************/
    /**
        @dev Update price of a given collateral type.
        @param _ilk   Collateral type
    */
    function updateCollateralPrice(bytes32 _ilk) public {
        Pricing(spotter()).poke(_ilk);
    }

    /****************************/
    /*** System Configuration ***/
    /****************************/
    /**
        @dev Set a contract in another contract, defining the relationship (ex. set a new Calc contract in Clip)
        @param _base   The address of the contract where the new contract address will be filed
        @param _what   Name of contract to file
        @param _addr   Address of contract to file
    */
    function setContract(address _base, bytes32 _what, address _addr) public {
        Fileable(_base).file(_what, _addr);
    }
    /**
        @dev Set a contract in another contract, defining the relationship (ex. set a new Calc contract in a Clip)
        @param _base   The address of the contract where the new contract address will be filed
        @param _ilk    Collateral type
        @param _what   Name of contract to file
        @param _addr   Address of contract to file
    */
    function setContract(address _base, bytes32 _ilk, bytes32 _what, address _addr) public {
        Fileable(_base).file(_ilk, _what, _addr);
    }
    /**
        @dev Set a value in a contract, via a governance authorized File pattern.
        @param _base   The address of the contract where the new contract address will be filed
        @param _what   Name of tag for the value (e.x. "Line")
        @param _amt    The value to set or update
    */
    function setValue(address _base, bytes32 _what, uint256 _amt) public {
        Fileable(_base).file(_what, _amt);
    }
    /**
        @dev Set an ilk-specific value in a contract, via a governance authorized File pattern.
        @param _base   The address of the contract where the new value will be filed
        @param _ilk    Collateral type
        @param _what   Name of tag for the value (e.x. "Line")
        @param _amt    The value to set or update
    */
    function setValue(address _base, bytes32 _ilk, bytes32 _what, uint256 _amt) public {
        Fileable(_base).file(_ilk, _what, _amt);
    }

    /******************************/
    /*** System Risk Parameters ***/
    /******************************/
    // function setGlobalDebtCeiling(uint256 _amount) public { setGlobalDebtCeiling(vat(), _amount); }
    /**
        @dev Set the global debt ceiling. Amount will be converted to the correct internal precision.
        @param _amount The amount to set in DAI (ex. 10m DAI amount == 10000000)
    */
    function setGlobalDebtCeiling(uint256 _amount) public {
        require(_amount < WAD);  // "LibDssExec/incorrect-global-Line-precision"
        setValue(vat(), "Line", _amount * RAD);
    }
    /**
        @dev Increase the global debt ceiling by a specific amount. Amount will be converted to the correct internal precision.
        @param _amount The amount to add in DAI (ex. 10m DAI amount == 10000000)
    */
    function increaseGlobalDebtCeiling(uint256 _amount) public {
        require(_amount < WAD);  // "LibDssExec/incorrect-Line-increase-precision"
        address _vat = vat();
        setValue(_vat, "Line", DssVat(_vat).Line() + _amount * RAD);
    }
    /**
        @dev Decrease the global debt ceiling by a specific amount. Amount will be converted to the correct internal precision.
        @param _amount The amount to reduce in DAI (ex. 10m DAI amount == 10000000)
    */
    function decreaseGlobalDebtCeiling(uint256 _amount) public {
        require(_amount < WAD);  // "LibDssExec/incorrect-Line-decrease-precision"
        address _vat = vat();
        setValue(_vat, "Line", DssVat(_vat).Line() - _amount * RAD);
    }
    /**
        @dev Set the Dai Savings Rate. See: docs/rates.txt
        @param _rate   The accumulated rate (ex. 4% => 1000000001243680656318820312)
        @param _doDrip `true` to accumulate interest owed
    */
    function setDSR(uint256 _rate, bool _doDrip) public {
        require((_rate >= RAY) && (_rate <= RATES_ONE_HUNDRED_PCT));  // "LibDssExec/dsr-out-of-bounds"
        if (_doDrip) Drippable(pot()).drip();
        setValue(pot(), "dsr", _rate);
    }
    /**
        @dev Set the DAI amount for system surplus auctions. Amount will be converted to the correct internal precision.
        @param _amount The amount to set in DAI (ex. 10m DAI amount == 10000000)
    */
    function setSurplusAuctionAmount(uint256 _amount) public {
        require(_amount < WAD);  // "LibDssExec/incorrect-vow-bump-precision"
        setValue(vow(), "bump", _amount * RAD);
    }
    /**
        @dev Set the DAI amount for system surplus buffer, must be exceeded before surplus auctions start. Amount will be converted to the correct internal precision.
        @param _amount The amount to set in DAI (ex. 10m DAI amount == 10000000)
    */
    function setSurplusBuffer(uint256 _amount) public {
        require(_amount < WAD);  // "LibDssExec/incorrect-vow-hump-precision"
        setValue(vow(), "hump", _amount * RAD);
    }
    /**
        @dev Set minimum bid increase for surplus auctions. Amount will be converted to the correct internal precision.
        @dev Equation used for conversion is (1 + pct / 10,000) * WAD
        @param _pct_bps The pct, in basis points, to set in integer form (x100). (ex. 5% = 5 * 100 = 500)
    */
    function setMinSurplusAuctionBidIncrease(uint256 _pct_bps) public {
        require(_pct_bps < BPS_ONE_HUNDRED_PCT);  // "LibDssExec/incorrect-flap-beg-precision"
        setValue(flap(), "beg", WAD + wdiv(_pct_bps, BPS_ONE_HUNDRED_PCT));
    }
    /**
        @dev Set bid duration for surplus auctions.
        @param _duration Amount of time for bids. (in seconds)
    */
    function setSurplusAuctionBidDuration(uint256 _duration) public {
        setValue(flap(), "ttl", _duration);
    }
    /**
        @dev Set total auction duration for surplus auctions.
        @param _duration Amount of time for auctions. (in seconds)
    */
    function setSurplusAuctionDuration(uint256 _duration) public {
        setValue(flap(), "tau", _duration);
    }
    /**
        @dev Set the number of seconds that pass before system debt is auctioned for MKR tokens.
        @param _duration Duration in seconds
    */
    function setDebtAuctionDelay(uint256 _duration) public {
        setValue(vow(), "wait", _duration);
    }
    /**
        @dev Set the DAI amount for system debt to be covered by each debt auction. Amount will be converted to the correct internal precision.
        @param _amount The amount to set in DAI (ex. 10m DAI amount == 10000000)
    */
    function setDebtAuctionDAIAmount(uint256 _amount) public {
        require(_amount < WAD);  // "LibDssExec/incorrect-vow-sump-precision"
        setValue(vow(), "sump", _amount * RAD);
    }
    /**
        @dev Set the starting MKR amount to be auctioned off to cover system debt in debt auctions. Amount will be converted to the correct internal precision.
        @param _amount The amount to set in MKR (ex. 250 MKR amount == 250)
    */
    function setDebtAuctionMKRAmount(uint256 _amount) public {
        require(_amount < WAD);  // "LibDssExec/incorrect-vow-dump-precision"
        setValue(vow(), "dump", _amount * WAD);
    }
    /**
        @dev Set minimum bid increase for debt auctions. Amount will be converted to the correct internal precision.
        @dev Equation used for conversion is (1 + pct / 10,000) * WAD
        @param _pct_bps    The pct, in basis points, to set in integer form (x100). (ex. 5% = 5 * 100 = 500)
    */
    function setMinDebtAuctionBidIncrease(uint256 _pct_bps) public {
        require(_pct_bps < BPS_ONE_HUNDRED_PCT);  // "LibDssExec/incorrect-flop-beg-precision"
        setValue(flop(), "beg", WAD + wdiv(_pct_bps, BPS_ONE_HUNDRED_PCT));
    }
    /**
        @dev Set bid duration for debt auctions.
        @param _duration Amount of time for bids. (seconds)
    */
    function setDebtAuctionBidDuration(uint256 _duration) public {
        require(_duration < type(uint48).max);  // "LibDssExec/incorrect-flop-ttl-precision"
        setValue(flop(), "ttl", _duration);
    }
    /**
        @dev Set total auction duration for debt auctions.
        @param _duration Amount of time for auctions. (seconds)
    */
    function setDebtAuctionDuration(uint256 _duration) public {
        require(_duration < type(uint48).max);  // "LibDssExec/incorrect-flop-tau-precision"
        setValue(flop(), "tau", _duration);
    }
    /**
        @dev Set the rate of increasing amount of MKR out for auction during debt auctions. Amount will be converted to the correct internal precision.
        @dev MKR amount is increased by this rate every "tick" (if auction duration has passed and no one has bid on the MKR)
        @dev Equation used for conversion is (1 + pct / 10,000) * WAD
        @param _pct_bps    The pct, in basis points, to set in integer form (x100). (ex. 5% = 5 * 100 = 500)
    */
    function setDebtAuctionMKRIncreaseRate(uint256 _pct_bps) public {
        require(_pct_bps < BPS_ONE_HUNDRED_PCT);  // "LibDssExec/incorrect-flop-pad-precision"
        setValue(flop(), "pad", WAD + wdiv(_pct_bps, BPS_ONE_HUNDRED_PCT));
    }
    /**
        @dev Set the maximum total DAI amount that can be out for liquidation in the system at any point. Amount will be converted to the correct internal precision.
        @param _amount The amount to set in DAI (ex. 250,000 DAI amount == 250000)
    */
    function setMaxTotalDAILiquidationAmount(uint256 _amount) public {
        require(_amount < WAD);  // "LibDssExec/incorrect-dog-Hole-precision"
        setValue(dog(), "Hole", _amount * RAD);
    }
    /**
        @dev (LIQ 1.2) Set the maximum total DAI amount that can be out for liquidation in the system at any point. Amount will be converted to the correct internal precision.
        @param _amount The amount to set in DAI (ex. 250,000 DAI amount == 250000)
    */
    function setMaxTotalDAILiquidationAmountLEGACY(uint256 _amount) public {
        require(_amount < WAD);  // "LibDssExec/incorrect-cat-box-amount"
        setValue(cat(), "box", _amount * RAD);
    }
    /**
        @dev Set the duration of time that has to pass during emergency shutdown before collateral can start being claimed by DAI holders.
        @param _duration Time in seconds to set for ES processing time
    */
    function setEmergencyShutdownProcessingTime(uint256 _duration) public {
        setValue(end(), "wait", _duration);
    }
    /**
        @dev Set the global stability fee (is not typically used, currently is 0).
            Many of the settings that change weekly rely on the rate accumulator
            described at https://docs.makerdao.com/smart-contract-modules/rates-module
            To check this yourself, use the following rate calculation (example 8%):

            $ bc -l <<< 'scale=27; e( l(1.08)/(60 * 60 * 24 * 365) )'

            A table of rates can also be found at:
            https://ipfs.io/ipfs/QmefQMseb3AiTapiAKKexdKHig8wroKuZbmLtPLv4u2YwW
        @param _rate   The accumulated rate (ex. 4% => 1000000001243680656318820312)
    */
    function setGlobalStabilityFee(uint256 _rate) public {
        require((_rate >= RAY) && (_rate <= RATES_ONE_HUNDRED_PCT));  // "LibDssExec/global-stability-fee-out-of-bounds"
        setValue(jug(), "base", _rate);
    }
    /**
        @dev Set the value of DAI in the reference asset (e.g. $1 per DAI). Value will be converted to the correct internal precision.
        @dev Equation used for conversion is value * RAY / 1000
        @param _value The value to set as integer (x1000) (ex. $1.025 == 1025)
    */
    function setDAIReferenceValue(uint256 _value) public {
        require(_value < WAD);  // "LibDssExec/incorrect-par-precision"
        setValue(spotter(), "par", rdiv(_value, 1000));
    }

    /*****************************/
    /*** Collateral Management ***/
    /*****************************/
    /**
        @dev Set a collateral debt ceiling. Amount will be converted to the correct internal precision.
        @param _ilk    The ilk to update (ex. bytes32("ETH-A"))
        @param _amount The amount to set in DAI (ex. 10m DAI amount == 10000000)
    */
    function setIlkDebtCeiling(bytes32 _ilk, uint256 _amount) public {
        require(_amount < WAD);  // "LibDssExec/incorrect-ilk-line-precision"
        setValue(vat(), _ilk, "line", _amount * RAD);
    }
    /**
        @dev Increase a collateral debt ceiling. Amount will be converted to the correct internal precision.
        @param _ilk    The ilk to update (ex. bytes32("ETH-A"))
        @param _amount The amount to increase in DAI (ex. 10m DAI amount == 10000000)
        @param _global If true, increases the global debt ceiling by _amount
    */
    function increaseIlkDebtCeiling(bytes32 _ilk, uint256 _amount, bool _global) public {
        require(_amount < WAD);  // "LibDssExec/incorrect-ilk-line-precision"
        address _vat = vat();
        (,,,uint256 line_,) = DssVat(_vat).ilks(_ilk);
        setValue(_vat, _ilk, "line", line_ + _amount * RAD);
        if (_global) { increaseGlobalDebtCeiling(_amount); }
    }
    /**
        @dev Decrease a collateral debt ceiling. Amount will be converted to the correct internal precision.
        @param _ilk    The ilk to update (ex. bytes32("ETH-A"))
        @param _amount The amount to decrease in DAI (ex. 10m DAI amount == 10000000)
        @param _global If true, decreases the global debt ceiling by _amount
    */
    function decreaseIlkDebtCeiling(bytes32 _ilk, uint256 _amount, bool _global) public {
        require(_amount < WAD);  // "LibDssExec/incorrect-ilk-line-precision"
        address _vat = vat();
        (,,,uint256 line_,) = DssVat(_vat).ilks(_ilk);
        setValue(_vat, _ilk, "line", line_ - _amount * RAD);
        if (_global) { decreaseGlobalDebtCeiling(_amount); }
    }
    /**
        @dev Set a RWA collateral debt ceiling by specifying its new oracle price.
        @param _ilk      The ilk to update (ex. bytes32("ETH-A"))
        @param _ceiling  The new debt ceiling in natural units (e.g. set 10m DAI as 10_000_000)
        @param _price    The new oracle price in natural units
        @dev note: _price should enable DAI to be drawn over the loan period while taking into
                   account the configured ink amount, interest rate and liquidation ratio
        @dev note: _price * WAD should be greater than or equal to the current oracle price
    */
    function setRWAIlkDebtCeiling(bytes32 _ilk, uint256 _ceiling, uint256 _price) public {
        require(_price < WAD);
        setIlkDebtCeiling(_ilk, _ceiling);
        RwaOracleLike(getChangelogAddress("MIP21_LIQUIDATION_ORACLE")).bump(_ilk, _price * WAD);
        updateCollateralPrice(_ilk);
    }
    /**
        @dev Set the parameters for an ilk in the "MCD_IAM_AUTO_LINE" auto-line
        @param _ilk    The ilk to update (ex. bytes32("ETH-A"))
        @param _amount The Maximum value (ex. 100m DAI amount == 100000000)
        @param _gap    The amount of Dai per step (ex. 5m Dai == 5000000)
        @param _ttl    The amount of time (in seconds)
    */
    function setIlkAutoLineParameters(bytes32 _ilk, uint256 _amount, uint256 _gap, uint256 _ttl) public {
        require(_amount < WAD);  // "LibDssExec/incorrect-auto-line-amount-precision"
        require(_gap < WAD);  // "LibDssExec/incorrect-auto-line-gap-precision"
        IAMLike(autoLine()).setIlk(_ilk, _amount * RAD, _gap * RAD, _ttl);
    }
    /**
        @dev Set the debt ceiling for an ilk in the "MCD_IAM_AUTO_LINE" auto-line without updating the time values
        @param _ilk    The ilk to update (ex. bytes32("ETH-A"))
        @param _amount The Maximum value (ex. 100m DAI amount == 100000000)
    */
    function setIlkAutoLineDebtCeiling(bytes32 _ilk, uint256 _amount) public {
        address _autoLine = autoLine();
        (, uint256 gap, uint48 ttl,,) = IAMLike(_autoLine).ilks(_ilk);
        require(gap != 0 && ttl != 0);  // "LibDssExec/auto-line-not-configured"
        IAMLike(_autoLine).setIlk(_ilk, _amount * RAD, uint256(gap), uint256(ttl));
    }
    /**
        @dev Remove an ilk in the "MCD_IAM_AUTO_LINE" auto-line
        @param _ilk    The ilk to remove (ex. bytes32("ETH-A"))
    */
    function removeIlkFromAutoLine(bytes32 _ilk) public {
        IAMLike(autoLine()).remIlk(_ilk);
    }
    /**
        @dev Set a collateral minimum vault amount. Amount will be converted to the correct internal precision.
        @param _ilk    The ilk to update (ex. bytes32("ETH-A"))
        @param _amount The amount to set in DAI (ex. 10m DAI amount == 10000000)
    */
    function setIlkMinVaultAmount(bytes32 _ilk, uint256 _amount) public {
        require(_amount < WAD);  // "LibDssExec/incorrect-ilk-dust-precision"
        (,, uint256 _hole,) = DogLike(dog()).ilks(_ilk);
        require(_amount <= _hole / RAD);  // Ensure ilk.hole >= dust
        setValue(vat(), _ilk, "dust", _amount * RAD);
        (bool ok,) = clip(_ilk).call(abi.encodeWithSignature("upchost()")); ok;
    }
    /**
        @dev Set a collateral liquidation penalty. Amount will be converted to the correct internal precision.
        @dev Equation used for conversion is (1 + pct / 10,000) * WAD
        @param _ilk    The ilk to update (ex. bytes32("ETH-A"))
        @param _pct_bps    The pct, in basis points, to set in integer form (x100). (ex. 10.25% = 10.25 * 100 = 1025)
    */
    function setIlkLiquidationPenalty(bytes32 _ilk, uint256 _pct_bps) public {
        require(_pct_bps < BPS_ONE_HUNDRED_PCT);  // "LibDssExec/incorrect-ilk-chop-precision"
        setValue(dog(), _ilk, "chop", WAD + wdiv(_pct_bps, BPS_ONE_HUNDRED_PCT));
        (bool ok,) = clip(_ilk).call(abi.encodeWithSignature("upchost()")); ok;
    }
    /**
        @dev Set max DAI amount for liquidation per vault for collateral. Amount will be converted to the correct internal precision.
        @param _ilk    The ilk to update (ex. bytes32("ETH-A"))
        @param _amount The amount to set in DAI (ex. 10m DAI amount == 10000000)
    */
    function setIlkMaxLiquidationAmount(bytes32 _ilk, uint256 _amount) public {
        require(_amount < WAD);  // "LibDssExec/incorrect-ilk-hole-precision"
        setValue(dog(), _ilk, "hole", _amount * RAD);
    }
    /**
        @dev Set a collateral liquidation ratio. Amount will be converted to the correct internal precision.
        @dev Equation used for conversion is pct * RAY / 10,000
        @param _ilk    The ilk to update (ex. bytes32("ETH-A"))
        @param _pct_bps    The pct, in basis points, to set in integer form (x100). (ex. 150% = 150 * 100 = 15000)
    */
    function setIlkLiquidationRatio(bytes32 _ilk, uint256 _pct_bps) public {
        require(_pct_bps < 10 * BPS_ONE_HUNDRED_PCT); // "LibDssExec/incorrect-ilk-mat-precision" // Fails if pct >= 1000%
        require(_pct_bps >= BPS_ONE_HUNDRED_PCT); // the liquidation ratio has to be bigger or equal to 100%
        setValue(spotter(), _ilk, "mat", rdiv(_pct_bps, BPS_ONE_HUNDRED_PCT));
    }
    /**
        @dev Set an auction starting multiplier. Amount will be converted to the correct internal precision.
        @dev Equation used for conversion is pct * RAY / 10,000
        @param _ilk      The ilk to update (ex. bytes32("ETH-A"))
        @param _pct_bps  The pct, in basis points, to set in integer form (x100). (ex. 1.3x starting multiplier = 130% = 13000)
    */
    function setStartingPriceMultiplicativeFactor(bytes32 _ilk, uint256 _pct_bps) public {
        require(_pct_bps < 10 * BPS_ONE_HUNDRED_PCT); // "LibDssExec/incorrect-ilk-mat-precision" // Fails if gt 10x
        require(_pct_bps >= BPS_ONE_HUNDRED_PCT); // fail if start price is less than OSM price
        setValue(clip(_ilk), "buf", rdiv(_pct_bps, BPS_ONE_HUNDRED_PCT));
    }

    /**
        @dev Set the amout of time before an auction resets.
        @param _ilk      The ilk to update (ex. bytes32("ETH-A"))
        @param _duration Amount of time before auction resets (in seconds).
    */
    function setAuctionTimeBeforeReset(bytes32 _ilk, uint256 _duration) public {
        setValue(clip(_ilk), "tail", _duration);
    }

    /**
        @dev Percentage drop permitted before auction reset
        @param _ilk     The ilk to update (ex. bytes32("ETH-A"))
        @param _pct_bps The pct, in basis points, of drop to permit (x100).
    */
    function setAuctionPermittedDrop(bytes32 _ilk, uint256 _pct_bps) public {
        require(_pct_bps < BPS_ONE_HUNDRED_PCT); // "LibDssExec/incorrect-clip-cusp-value"
        setValue(clip(_ilk), "cusp", rdiv(_pct_bps, BPS_ONE_HUNDRED_PCT));
    }

    /**
        @dev Percentage of tab to suck from vow to incentivize keepers. Amount will be converted to the correct internal precision.
        @param _ilk     The ilk to update (ex. bytes32("ETH-A"))
        @param _pct_bps The pct, in basis points, of the tab to suck. (0.01% == 1)
    */
    function setKeeperIncentivePercent(bytes32 _ilk, uint256 _pct_bps) public {
        require(_pct_bps < BPS_ONE_HUNDRED_PCT); // "LibDssExec/incorrect-clip-chip-precision"
        setValue(clip(_ilk), "chip", wdiv(_pct_bps, BPS_ONE_HUNDRED_PCT));
    }

    /**
        @dev Set max DAI amount for flat rate keeper incentive. Amount will be converted to the correct internal precision.
        @param _ilk    The ilk to update (ex. bytes32("ETH-A"))
        @param _amount The amount to set in DAI (ex. 1000 DAI amount == 1000)
    */
    function setKeeperIncentiveFlatRate(bytes32 _ilk, uint256 _amount) public {
        require(_amount < WAD); // "LibDssExec/incorrect-clip-tip-precision"
        setValue(clip(_ilk), "tip", _amount * RAD);
    }

    /**
        @dev Sets the circuit breaker price tolerance in the clipper mom.
            This is somewhat counter-intuitive,
             to accept a 25% price drop, use a value of 75%
        @param _clip    The clipper to set the tolerance for
        @param _pct_bps The pct, in basis points, to set in integer form (x100). (ex. 5% = 5 * 100 = 500)
    */
    function setLiquidationBreakerPriceTolerance(address _clip, uint256 _pct_bps) public {
        require(_pct_bps < BPS_ONE_HUNDRED_PCT);  // "LibDssExec/incorrect-clippermom-price-tolerance"
        MomLike(clipperMom()).setPriceTolerance(_clip, rdiv(_pct_bps, BPS_ONE_HUNDRED_PCT));
    }

    /**
        @dev Set the stability fee for a given ilk.
            Many of the settings that change weekly rely on the rate accumulator
            described at https://docs.makerdao.com/smart-contract-modules/rates-module
            To check this yourself, use the following rate calculation (example 8%):

            $ bc -l <<< 'scale=27; e( l(1.08)/(60 * 60 * 24 * 365) )'

            A table of rates can also be found at:
            https://ipfs.io/ipfs/QmefQMseb3AiTapiAKKexdKHig8wroKuZbmLtPLv4u2YwW

        @param _ilk    The ilk to update (ex. bytes32("ETH-A") )
        @param _rate   The accumulated rate (ex. 4% => 1000000001243680656318820312)
        @param _doDrip `true` to accumulate stability fees for the collateral
    */
    function setIlkStabilityFee(bytes32 _ilk, uint256 _rate, bool _doDrip) public {
        require((_rate >= RAY) && (_rate <= RATES_ONE_HUNDRED_PCT));  // "LibDssExec/ilk-stability-fee-out-of-bounds"
        address _jug = jug();
        if (_doDrip) Drippable(_jug).drip(_ilk);

        setValue(_jug, _ilk, "duty", _rate);
    }

    /*************************/
    /*** Abacus Management ***/
    /*************************/

    /**
        @dev Set the number of seconds from the start when the auction reaches zero price.
        @dev Abacus:LinearDecrease only.
        @param _calc     The address of the LinearDecrease pricing contract
        @param _duration Amount of time for auctions.
    */
    function setLinearDecrease(address _calc, uint256 _duration) public {
        setValue(_calc, "tau", _duration);
    }

    /**
        @dev Set the number of seconds for each price step.
        @dev Abacus:StairstepExponentialDecrease only.
        @param _calc     The address of the StairstepExponentialDecrease pricing contract
        @param _duration Length of time between price drops [seconds]
        @param _pct_bps Per-step multiplicative factor in basis points. (ex. 99% == 9900)
    */
    function setStairstepExponentialDecrease(address _calc, uint256 _duration, uint256 _pct_bps) public {
        require(_pct_bps < BPS_ONE_HUNDRED_PCT); // DssExecLib/cut-too-high
        setValue(_calc, "cut", rdiv(_pct_bps, BPS_ONE_HUNDRED_PCT));
        setValue(_calc, "step", _duration);
    }
    /**
        @dev Set the number of seconds for each price step. (99% cut = 1% price drop per step)
             Amounts will be converted to the correct internal precision.
        @dev Abacus:ExponentialDecrease only
        @param _calc     The address of the ExponentialDecrease pricing contract
        @param _pct_bps Per-step multiplicative factor in basis points. (ex. 99% == 9900)
    */
    function setExponentialDecrease(address _calc, uint256 _pct_bps) public {
        require(_pct_bps < BPS_ONE_HUNDRED_PCT); // DssExecLib/cut-too-high
        setValue(_calc, "cut", rdiv(_pct_bps, BPS_ONE_HUNDRED_PCT));
    }

    /*************************/
    /*** Oracle Management ***/
    /*************************/
    /**
        @dev Allows an oracle to read prices from its source feeds
        @param _oracle  An OSM or LP oracle contract
    */
    function whitelistOracleMedians(address _oracle) public {
        (bool ok, bytes memory data) = _oracle.call(abi.encodeWithSignature("orb0()"));
        if (ok) {
            // Token is an LP oracle
            address median0 = abi.decode(data, (address));
            addReaderToWhitelistCall(median0, _oracle);
            addReaderToWhitelistCall(OracleLike_0(_oracle).orb1(), _oracle);
        } else {
            // Standard OSM
            addReaderToWhitelistCall(OracleLike_0(_oracle).src(), _oracle);
        }
    }
    /**
        @dev Adds an address to the OSM or Median's reader whitelist, allowing the address to read prices.
        @param _oracle        Oracle Security Module (OSM) or Median core contract address
        @param _reader     Address to add to whitelist
    */
    function addReaderToWhitelist(address _oracle, address _reader) public {
        OracleLike_0(_oracle).kiss(_reader);
    }
    /**
        @dev Removes an address to the OSM or Median's reader whitelist, disallowing the address to read prices.
        @param _oracle     Oracle Security Module (OSM) or Median core contract address
        @param _reader     Address to remove from whitelist
    */
    function removeReaderFromWhitelist(address _oracle, address _reader) public {
        OracleLike_0(_oracle).diss(_reader);
    }
    /**
        @dev Adds an address to the OSM or Median's reader whitelist, allowing the address to read prices.
        @param _oracle  OSM or Median core contract address
        @param _reader  Address to add to whitelist
    */
    function addReaderToWhitelistCall(address _oracle, address _reader) public {
        (bool ok,) = _oracle.call(abi.encodeWithSignature("kiss(address)", _reader)); ok;
    }
    /**
        @dev Removes an address to the OSM or Median's reader whitelist, disallowing the address to read prices.
        @param _oracle  Oracle Security Module (OSM) or Median core contract address
        @param _reader  Address to remove from whitelist
    */
    function removeReaderFromWhitelistCall(address _oracle, address _reader) public {
        (bool ok,) = _oracle.call(abi.encodeWithSignature("diss(address)", _reader)); ok;
    }
    /**
        @dev Sets the minimum number of valid messages from whitelisted oracle feeds needed to update median price.
        @param _median     Median core contract address
        @param _minQuorum  Minimum number of valid messages from whitelisted oracle feeds needed to update median price (NOTE: MUST BE ODD NUMBER)
    */
    function setMedianWritersQuorum(address _median, uint256 _minQuorum) public {
        OracleLike_0(_median).setBar(_minQuorum);
    }
    /**
        @dev Add OSM address to OSM mom, allowing it to be frozen by governance.
        @param _osm        Oracle Security Module (OSM) core contract address
        @param _ilk        Collateral type using OSM
    */
    function allowOSMFreeze(address _osm, bytes32 _ilk) public {
        MomLike(osmMom()).setOsm(_ilk, _osm);
    }

    /*****************************/
    /*** Direct Deposit Module ***/
    /*****************************/

    /**
        @dev Sets the target rate threshold for a dai direct deposit module (d3m)
        @dev Aave: Targets the variable borrow rate
        @param _d3m     The address of the D3M contract
        @param _pct_bps Target rate in basis points. (ex. 4% == 400)
    */
    function setD3MTargetInterestRate(address _d3m, uint256 _pct_bps) public {
        require(_pct_bps < BPS_ONE_HUNDRED_PCT); // DssExecLib/bar-too-high
        setValue(_d3m, "bar", rdiv(_pct_bps, BPS_ONE_HUNDRED_PCT));
    }

    /*****************************/
    /*** Collateral Onboarding ***/
    /*****************************/

    /**
        @dev Performs basic functions and sanity checks to add a new collateral type to the MCD system
        @param _ilk      Collateral type key code [Ex. "ETH-A"]
        @param _gem      Address of token contract
        @param _join     Address of join adapter
        @param _clip     Address of liquidation agent
        @param _calc     Address of the pricing function
        @param _pip      Address of price feed
    */
    function addCollateralBase(
        bytes32 _ilk,
        address _gem,
        address _join,
        address _clip,
        address _calc,
        address _pip
    ) public {
        // Sanity checks
        address _vat = vat();
        address _dog = dog();
        address _spotter = spotter();
        require(JoinLike(_join).vat() == _vat);     // "join-vat-not-match"
        require(JoinLike(_join).ilk() == _ilk);     // "join-ilk-not-match"
        require(JoinLike(_join).gem() == _gem);     // "join-gem-not-match"
        require(JoinLike(_join).dec() ==
                   ERC20(_gem).decimals());         // "join-dec-not-match"
        require(ClipLike(_clip).vat() == _vat);     // "clip-vat-not-match"
        require(ClipLike(_clip).dog() == _dog);     // "clip-dog-not-match"
        require(ClipLike(_clip).ilk() == _ilk);     // "clip-ilk-not-match"
        require(ClipLike(_clip).spotter() == _spotter);  // "clip-ilk-not-match"

        // Set the token PIP in the Spotter
        setContract(spotter(), _ilk, "pip", _pip);

        // Set the ilk Clipper in the Dog
        setContract(_dog, _ilk, "clip", _clip);
        // Set vow in the clip
        setContract(_clip, "vow", vow());
        // Set the pricing function for the Clipper
        setContract(_clip, "calc", _calc);

        // Init ilk in Vat & Jug
        Initializable(_vat).init(_ilk);  // Vat
        Initializable(jug()).init(_ilk);  // Jug

        // Allow ilk Join to modify Vat registry
        authorize(_vat, _join);
        // Allow ilk Join to suck dai for keepers
        authorize(_vat, _clip);
        // Allow the ilk Clipper to reduce the Dog hole on deal()
        authorize(_dog, _clip);
        // Allow Dog to kick auctions in ilk Clipper
        authorize(_clip, _dog);
        // Allow End to yank auctions in ilk Clipper
        authorize(_clip, end());
        // Authorize the ESM to execute in the clipper
        authorize(_clip, esm());

        // Add new ilk to the IlkRegistry
        RegistryLike(reg()).add(_join);
    }

    // Complete collateral onboarding logic.
    function addNewCollateral(CollateralOpts memory co) public {
        // Add the collateral to the system.
        addCollateralBase(co.ilk, co.gem, co.join, co.clip, co.calc, co.pip);
        address clipperMom_ = clipperMom();

        if (!co.isLiquidatable) {
            // Disallow Dog to kick auctions in ilk Clipper
            setValue(co.clip, "stopped", 3);
        } else {
            // Grant ClipperMom access to the ilk Clipper
            authorize(co.clip, clipperMom_);
        }

        if(co.isOSM) { // If pip == OSM
            // Allow OsmMom to access to the TOKEN OSM
            authorize(co.pip, osmMom());
            if (co.whitelistOSM) { // If median is src in OSM
                // Whitelist OSM to read the Median data (only necessary if it is the first time the token is being added to an ilk)
                whitelistOracleMedians(co.pip);
            }
            // Whitelist Spotter to read the OSM data (only necessary if it is the first time the token is being added to an ilk)
            addReaderToWhitelist(co.pip, spotter());
            // Whitelist Clipper on pip
            addReaderToWhitelist(co.pip, co.clip);
            // Allow the clippermom to access the feed
            addReaderToWhitelist(co.pip, clipperMom_);
            // Whitelist End to read the OSM data (only necessary if it is the first time the token is being added to an ilk)
            addReaderToWhitelist(co.pip, end());
            // Set TOKEN OSM in the OsmMom for new ilk
            allowOSMFreeze(co.pip, co.ilk);
        }
        // Increase the global debt ceiling by the ilk ceiling
        increaseGlobalDebtCeiling(co.ilkDebtCeiling);

        // Set the ilk debt ceiling
        setIlkDebtCeiling(co.ilk, co.ilkDebtCeiling);

        // Set the hole size
        setIlkMaxLiquidationAmount(co.ilk, co.maxLiquidationAmount);

        // Set the ilk dust
        setIlkMinVaultAmount(co.ilk, co.minVaultAmount);

        // Set the ilk liquidation penalty
        setIlkLiquidationPenalty(co.ilk, co.liquidationPenalty);

        // Set the ilk stability fee
        setIlkStabilityFee(co.ilk, co.ilkStabilityFee, true);

        // Set the auction starting price multiplier
        setStartingPriceMultiplicativeFactor(co.ilk, co.startingPriceFactor);

        // Set the amount of time before an auction resets.
        setAuctionTimeBeforeReset(co.ilk, co.auctionDuration);

        // Set the allowed auction drop percentage before reset
        setAuctionPermittedDrop(co.ilk, co.permittedDrop);

        // Set the ilk min collateralization ratio
        setIlkLiquidationRatio(co.ilk, co.liquidationRatio);

        // Set the price tolerance in the liquidation circuit breaker
        setLiquidationBreakerPriceTolerance(co.clip, co.breakerTolerance);

        // Set a flat rate for the keeper reward
        setKeeperIncentiveFlatRate(co.ilk, co.kprFlatReward);

        // Set the percentage of liquidation as keeper award
        setKeeperIncentivePercent(co.ilk, co.kprPctReward);

        // Update ilk spot value in Vat
        updateCollateralPrice(co.ilk);
    }

    /***************/
    /*** Payment ***/
    /***************/
    /**
        @dev Send a payment in ERC20 DAI from the surplus buffer.
        @param _target The target address to send the DAI to.
        @param _amount The amount to send in DAI (ex. 10m DAI amount == 10000000)
    */
    function sendPaymentFromSurplusBuffer(address _target, uint256 _amount) public {
        require(_amount < WAD);  // "LibDssExec/incorrect-ilk-line-precision"
        DssVat(vat()).suck(vow(), address(this), _amount * RAD);
        JoinLike(daiJoin()).exit(_target, _amount * WAD);
    }

    /************/
    /*** Misc ***/
    /************/
    /**
        @dev Initiate linear interpolation on an administrative value over time.
        @param _name        The label for this lerp instance
        @param _target      The target contract
        @param _what        The target parameter to adjust
        @param _startTime   The time for this lerp
        @param _start       The start value for the target parameter
        @param _end         The end value for the target parameter
        @param _duration    The duration of the interpolation
    */
    function linearInterpolation(bytes32 _name, address _target, bytes32 _what, uint256 _startTime, uint256 _start, uint256 _end, uint256 _duration) public returns (address) {
        address lerp = LerpFactoryLike(lerpFab()).newLerp(_name, _target, _what, _startTime, _start, _end, _duration);
        Authorizable(_target).rely(lerp);
        LerpLike(lerp).tick();
        return lerp;
    }
    /**
        @dev Initiate linear interpolation on an administrative value over time.
        @param _name        The label for this lerp instance
        @param _target      The target contract
        @param _ilk         The ilk to target
        @param _what        The target parameter to adjust
        @param _startTime   The time for this lerp
        @param _start       The start value for the target parameter
        @param _end         The end value for the target parameter
        @param _duration    The duration of the interpolation
    */
    function linearInterpolation(bytes32 _name, address _target, bytes32 _ilk, bytes32 _what, uint256 _startTime, uint256 _start, uint256 _end, uint256 _duration) public returns (address) {
        address lerp = LerpFactoryLike(lerpFab()).newIlkLerp(_name, _target, _ilk, _what, _startTime, _start, _end, _duration);
        Authorizable(_target).rely(lerp);
        LerpLike(lerp).tick();
        return lerp;
    }
}

// lib/dss-exec-lib/src/DssAction.sol

//
// DssAction.sol -- DSS Executive Spell Actions
//
// Copyright (C) 2020-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/>.

interface OracleLike_1 {
    function src() external view returns (address);
}

abstract contract DssAction {

    using DssExecLib for *;

    // Modifier used to limit execution time when office hours is enabled
    modifier limited {
        require(DssExecLib.canCast(uint40(block.timestamp), officeHours()), "Outside office hours");
        _;
    }

    // Office Hours defaults to true by default.
    //   To disable office hours, override this function and
    //    return false in the inherited action.
    function officeHours() public view virtual returns (bool) {
        return true;
    }

    // DssExec calls execute. We limit this function subject to officeHours modifier.
    function execute() external limited {
        actions();
    }

    // DssAction developer must override `actions()` and place all actions to be called inside.
    //   The DssExec function will call this subject to the officeHours limiter
    //   By keeping this function public we allow simulations of `execute()` on the actions outside of the cast time.
    function actions() public virtual;

    // Provides a descriptive tag for bot consumption
    // This should be modified weekly to provide a summary of the actions
    // Hash: seth keccak -- "$(wget https://<executive-vote-canonical-post> -q -O - 2>/dev/null)"
    function description() external view virtual returns (string memory);

    // Returns the next available cast time
    function nextCastTime(uint256 eta) external view returns (uint256 castTime) {
        require(eta <= type(uint40).max);
        castTime = DssExecLib.nextCastTime(uint40(eta), uint40(block.timestamp), officeHours());
    }
}

// src/dependencies/06-farm/phase-1b/UsdsSkyFarmingInit.sol

//
// 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/>.

struct UsdsSkyFarmingInitParams {
    address usds;
    address sky;
    address rewards;
    bytes32 rewardsKey; // Chainlog key
    address dist;
    bytes32 distKey; // Chainlog key
    address vest;
    uint256 vestTot;
    uint256 vestBgn;
    uint256 vestTau;
}

struct UsdsSkyFarmingInitResult {
    uint256 vestId;
}

library UsdsSkyFarmingInit {
    ChainlogLike_3 internal constant chainlog = ChainlogLike_3(0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F);

    function init(UsdsSkyFarmingInitParams memory p) internal returns (UsdsSkyFarmingInitResult memory r) {
        require(DssVestWithGemLike(p.vest).gem() == p.sky, "UsdsSkyFarmingInit/vest-gem-mismatch");

        require(
            StakingRewardsLike_2(p.rewards).stakingToken() == p.usds,
            "UsdsSkyFarmingInit/rewards-staking-token-mismatch"
        );
        require(
            StakingRewardsLike_2(p.rewards).rewardsToken() == p.sky,
            "UsdsSkyFarmingInit/rewards-rewards-token-mismatch"
        );
        require(StakingRewardsLike_2(p.rewards).rewardRate() == 0, "UsdsSkyFarmingInit/reward-rate-not-zero");
        require(
            StakingRewardsLike_2(p.rewards).rewardsDistribution() == address(0),
            "UsdsSkyFarmingInit/rewards-distribution-already-set"
        );
        require(
            StakingRewardsLike_2(p.rewards).owner() == chainlog.getAddress("MCD_PAUSE_PROXY"),
            "UsdsSkyFarmingInit/invalid-owner"
        );

        require(VestedRewardsDistributionLike_1(p.dist).gem() == p.sky, "UsdsSkyFarmingInit/dist-gem-mismatch");
        require(VestedRewardsDistributionLike_1(p.dist).dssVest() == p.vest, "UsdsSkyFarmingInit/dist-dss-vest-mismatch");
        require(
            VestedRewardsDistributionLike_1(p.dist).stakingRewards() == p.rewards,
            "UsdsSkyFarmingInit/dist-staking-rewards-mismatch"
        );

        // `vest` is expected to be an instance of `DssVestMintable`.
        // Check if minting rights on `sky` were granted to `vest`.
        require(WardsLike(p.sky).wards(p.vest) == 1, "UsdsSkyFarmingInit/missing-sky-rely-vest");
        // Set `dist` with  `rewardsDistribution` role in `rewards`.
        StakingRewardsInit.init(p.rewards, StakingRewardsInitParams({dist: p.dist}));

        // Create the proper vesting stream for rewards distribution.
        uint256 vestId = VestInit.create(
            p.vest,
            VestCreateParams({usr: p.dist, tot: p.vestTot, bgn: p.vestBgn, tau: p.vestTau, eta: 0})
        );

        // Set the `vestId` in `dist`
        VestedRewardsDistributionInit.init(p.dist, VestedRewardsDistributionInitParams({vestId: vestId}));

        r.vestId = vestId;

        chainlog.setAddress(p.rewardsKey, p.rewards);
        chainlog.setAddress(p.distKey, p.dist);
    }
}

interface WardsLike {
    function wards(address who) external view returns (uint256);
}

interface DssVestWithGemLike {
    function gem() external view returns (address);
}

interface StakingRewardsLike_2 {
    function owner() external view returns (address);

    function rewardRate() external view returns (uint256);

    function rewardsDistribution() external view returns (address);

    function rewardsToken() external view returns (address);

    function stakingToken() external view returns (address);
}

interface VestedRewardsDistributionLike_1 {
    function dssVest() external view returns (address);

    function gem() external view returns (address);

    function stakingRewards() external view returns (address);
}

interface ChainlogLike_3 {
    function getAddress(bytes32 key) external view returns (address);

    function setAddress(bytes32 key, address addr) external;
}

// lib/dss-test/lib/dss-interfaces/src/Interfaces.sol

// MIP21 Abstracts

// Partial DSS Abstracts

// lib/dss-test/src/GodMode.sol
// SPDX-FileCopyrightText: © 2022 Dai Foundation <www.daifoundation.org>

//
// 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/>.

library GodMode {

    address constant public VM_ADDR = address(bytes20(uint160(uint256(keccak256('hevm cheat code')))));

    function vm() internal pure returns (Vm) {
        return Vm(VM_ADDR);
    }

    /// @dev Set the ward for `base` for the specified `target`
    /// Note this only works for contracts compiled under Solidity. Vyper contracts use a different storage structure for maps.
    /// See https://twitter.com/msolomon44/status/1420137730009300992?t=WO2052xM3AzUCL7o7Pfkow&s=19
    function setWard(address base, address target, uint256 val) internal {

        // Edge case - ward is already set
        if (WardsAbstract(base).wards(target) == val) return;

        for (int i = 0; i < 100; i++) {
            // Scan the storage for the ward storage slot
            bytes32 prevValue = vm().load(
                address(base),
                keccak256(abi.encode(target, uint256(i)))
            );
            vm().store(
                address(base),
                keccak256(abi.encode(target, uint256(i))),
                bytes32(uint256(val))
            );
            if (WardsAbstract(base).wards(target) == val) {
                // Found it
                return;
            } else {
                // Keep going after restoring the original value
                vm().store(
                    address(base),
                    keccak256(abi.encode(target, uint256(i))),
                    prevValue
                );
            }
        }

        // We have failed if we reach here
        revert("Could not give auth access");
    }

    /// @dev Set the ward for `base` for the specified `target`
    /// Note this only works for contracts compiled under Solidity. Vyper contracts use a different storage structure for maps.
    /// See https://twitter.com/msolomon44/status/1420137730009300992?t=WO2052xM3AzUCL7o7Pfkow&s=19
    function setWard(WardsAbstract base, address target, uint256 val) internal {
        setWard(address(base), target, val);
    }

    /// @dev Set the ward for `base` for the specified `target`
    /// Note this only works for contracts compiled under Solidity. Vyper contracts use a different storage structure for maps.
    /// See https://twitter.com/msolomon44/status/1420137730009300992?t=WO2052xM3AzUCL7o7Pfkow&s=19
    function setWard(VatAbstract base, address target, uint256 val) internal {
        setWard(address(base), target, val);
    }

    /// @dev Sets the balance for `who` to `amount` for `token`.
    function setBalance(address token, address who, uint256 amount) internal {
        // Edge case - balance is already set for some reason
        if (DSTokenAbstract(token).balanceOf(who) == amount) return;

        for (uint256 i = 0; i < 200; i++) {
            // Scan the storage for the solidity-style balance storage slot
            {
                bytes32 prevValue = vm().load(
                    token,
                    keccak256(abi.encode(who, uint256(i)))
                );
                vm().store(
                    token,
                    keccak256(abi.encode(who, uint256(i))),
                    bytes32(amount)
                );
                if (DSTokenAbstract(token).balanceOf(who) == amount) {
                    // Found it
                    return;
                } else {
                    // Keep going after restoring the original value
                    vm().store(
                        token,
                        keccak256(abi.encode(who, uint256(i))),
                        prevValue
                    );
                }
            }

            // Vyper-style storage layout for maps
            {
                bytes32 prevValue = vm().load(
                    token,
                    keccak256(abi.encode(uint256(i), who))
                );

                vm().store(
                    token,
                    keccak256(abi.encode(uint256(i), who)),
                    bytes32(amount)
                );
                if (DSTokenAbstract(token).balanceOf(who) == amount) {
                    // Found it
                    return;
                } else {
                    // Keep going after restoring the original value
                    vm().store(
                        token,
                        keccak256(abi.encode(uint256(i), who)),
                        prevValue
                    );
                }
            }
        }

        // We have failed if we reach here
        revert("Could not give tokens");
    }

    /// @dev Sets the balance for `who` to `amount` for `token`.
    function setBalance(DSTokenAbstract token, address who, uint256 amount) internal {
        setBalance(address(token), who, amount);
    }

    /// @dev Sets the balance for `who` to `amount` for `token`.
    function setBalance(DaiAbstract token, address who, uint256 amount) internal {
        setBalance(address(token), who, amount);
    }

}

// lib/dss-test/src/MCD.sol
// SPDX-FileCopyrightText: © 2022 Dai Foundation <www.daifoundation.org>

//
// 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/>.

contract DSValue {
    bool    has;
    bytes32 val;
    function peek() public view returns (bytes32, bool) {
        return (val,has);
    }
    function read() external view returns (bytes32) {
        bytes32 wut; bool haz;
        (wut, haz) = peek();
        require(haz, "haz-not");
        return wut;
    }
    function poke(bytes32 wut) external {
        val = wut;
        has = true;
    }
    function void() external {
        val = bytes32(0);
        has = false;
    }
}

struct DssInstance {
    ChainlogAbstract chainlog;
    VatAbstract vat;
    DaiJoinAbstract daiJoin;
    DaiAbstract dai;
    VowAbstract vow;
    DogAbstract dog;
    PotAbstract pot;
    JugAbstract jug;
    SpotAbstract spotter;
    EndAbstract end;
    CureAbstract cure;
    FlapAbstract flap;
    FlopAbstract flop;
    ESMAbstract esm;
}

struct DssIlkInstance {
    DSTokenAbstract gem;
    OsmAbstract pip;
    GemJoinAbstract join;
    ClipAbstract clip;
}

library MCD {

    uint256 constant WAD = 10 ** 18;
    uint256 constant RAY = 10 ** 27;
    uint256 constant RAD = 10 ** 45;

    function getAddressOrNull(DssInstance memory dss, bytes32 key) internal view returns (address) {
        try dss.chainlog.getAddress(key) returns (address a) {
            return a;
        } catch {
            return address(0);
        }
    }

    function loadFromChainlog(address chainlog) internal view returns (DssInstance memory dss) {
        return loadFromChainlog(ChainlogAbstract(chainlog));
    }

    function loadFromChainlog(ChainlogAbstract chainlog) internal view returns (DssInstance memory dss) {
        dss.chainlog = chainlog;
        dss.vat = VatAbstract(getAddressOrNull(dss, "MCD_VAT"));
        dss.daiJoin = DaiJoinAbstract(getAddressOrNull(dss, "MCD_JOIN_DAI"));
        dss.dai = DaiAbstract(getAddressOrNull(dss, "MCD_DAI"));
        dss.vow = VowAbstract(getAddressOrNull(dss, "MCD_VOW"));
        dss.dog = DogAbstract(getAddressOrNull(dss, "MCD_DOG"));
        dss.pot = PotAbstract(getAddressOrNull(dss, "MCD_POT"));
        dss.jug = JugAbstract(getAddressOrNull(dss, "MCD_JUG"));
        dss.spotter = SpotAbstract(getAddressOrNull(dss, "MCD_SPOT"));
        dss.end = EndAbstract(getAddressOrNull(dss, "MCD_END"));
        dss.cure = CureAbstract(getAddressOrNull(dss, "MCD_CURE"));
        dss.flap = FlapAbstract(getAddressOrNull(dss, "MCD_FLAP"));
        dss.flop = FlopAbstract(getAddressOrNull(dss, "MCD_FLOP"));
        dss.esm = ESMAbstract(getAddressOrNull(dss, "MCD_ESM"));
    }

    function bytesToBytes32(bytes memory b) private pure returns (bytes32) {
        bytes32 out;
        for (uint256 i = 0; i < b.length; i++) {
            out |= bytes32(b[i] & 0xFF) >> (i * 8);
        }
        return out;
    }

    function getIlk(DssInstance memory dss, string memory gem, string memory variant) internal view returns (DssIlkInstance memory) {
        return DssIlkInstance(
            DSTokenAbstract(getAddressOrNull(dss, bytesToBytes32(bytes(gem)))),
            OsmAbstract(getAddressOrNull(dss, bytesToBytes32(abi.encodePacked("PIP_", gem)))),
            GemJoinAbstract(getAddressOrNull(dss, bytesToBytes32(abi.encodePacked("MCD_JOIN_", gem, "_", variant)))),
            ClipAbstract(getAddressOrNull(dss, bytesToBytes32(abi.encodePacked("MCD_CLIP_", gem, "_", variant))))
        );
    }

    /// @dev Initialize a dummy ilk with a $1 DSValue pip without liquidations
    function initIlk(
        DssInstance memory dss,
        bytes32 ilk
    ) internal {
        DSValue pip = new DSValue();
        pip.poke(bytes32(WAD));
        initIlk(dss, ilk, address(0), address(pip));
    }

    /// @dev Initialize an ilk with a $1 DSValue pip without liquidations
    function initIlk(
        DssInstance memory dss,
        bytes32 ilk,
        address join
    ) internal {
        DSValue pip = new DSValue();
        pip.poke(bytes32(WAD));
        initIlk(dss, ilk, join, address(pip));
    }

    /// @dev Initialize an ilk without liquidations
    function initIlk(
        DssInstance memory dss,
        bytes32 ilk,
        address join,
        address pip
    ) internal {
        dss.vat.init(ilk);
        dss.jug.init(ilk);

        dss.vat.rely(join);

        dss.spotter.file(ilk, "pip", pip);
        dss.spotter.file(ilk, "mat", RAY);
        dss.spotter.poke(ilk);
    }

    /// @dev Initialize an ilk with liquidations
    function initIlk(
        DssInstance memory dss,
        bytes32 ilk,
        address join,
        address pip,
        address clip,
        address clipCalc
    ) internal {
        initIlk(dss, ilk, join, pip);

        // TODO liquidations
        clip; clipCalc;
    }

    /// @dev Give who a ward on all core contracts
    function giveAdminAccess(DssInstance memory dss, address who) internal {
        if (address(dss.vat) != address(0)) GodMode.setWard(address(dss.vat), who, 1);
        if (address(dss.dai) != address(0)) GodMode.setWard(address(dss.dai), who, 1);
        if (address(dss.vow) != address(0)) GodMode.setWard(address(dss.vow), who, 1);
        if (address(dss.dog) != address(0)) GodMode.setWard(address(dss.dog), who, 1);
        if (address(dss.pot) != address(0)) GodMode.setWard(address(dss.pot), who, 1);
        if (address(dss.jug) != address(0)) GodMode.setWard(address(dss.jug), who, 1);
        if (address(dss.spotter) != address(0)) GodMode.setWard(address(dss.spotter), who, 1);
        if (address(dss.end) != address(0)) GodMode.setWard(address(dss.end), who, 1);
        if (address(dss.cure) != address(0)) GodMode.setWard(address(dss.cure), who, 1);
        if (address(dss.esm) != address(0)) GodMode.setWard(address(dss.esm), who, 1);
    }

    /// @dev Give who a ward on all core contracts to this address
    function giveAdminAccess(DssInstance memory dss) internal {
        giveAdminAccess(dss, address(this));
    }

    function newUser(DssInstance memory dss) internal returns (MCDUser) {
        return new MCDUser(dss);
    }

}

// lib/dss-test/src/MCDUser.sol
// SPDX-FileCopyrightText: © 2022 Dai Foundation <www.daifoundation.org>

//
// 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/>.

/// @dev A user which can perform actions in MCD
contract MCDUser {

    using GodMode for *;

    DssInstance dss;

    constructor(
        DssInstance memory _dss
    ) {
        dss = _dss;
    }

    /// @dev Create an auction on the provided ilk
    /// @param join The gem join adapter to use
    /// @param amount The amount of gems to use as collateral
    function createAuction(
        GemJoinAbstract join,
        uint256 amount
    ) public {
        DSTokenAbstract token = DSTokenAbstract(join.gem());
        bytes32 ilk = join.ilk();

        uint256 prevBalance = token.balanceOf(address(this));
        token.setBalance(address(this), amount);
        uint256 prevAllowance = token.allowance(address(this), address(join));
        token.approve(address(join), amount);
        join.join(address(this), amount);
        token.setBalance(address(this), prevBalance);
        token.approve(address(join), prevAllowance);
        (,uint256 rate, uint256 spot,,) = dss.vat.ilks(ilk);
        uint256 art = spot * amount / rate;
        uint256 ink = amount * (10 ** (18 - token.decimals()));
        dss.vat.frob(ilk, address(this), address(this), address(this), int256(ink), int256(art));

        // Temporarily increase the liquidation threshold to liquidate this one vault then reset it
        uint256 prevWard = dss.vat.wards(address(this));
        dss.vat.setWard(address(this), 1);
        dss.vat.file(ilk, "spot", spot / 2);
        dss.dog.bark(ilk, address(this), address(this));
        dss.vat.file(ilk, "spot", spot);
        dss.vat.setWard(address(this), prevWard);
    }

}

// src/dependencies/04-univ2-pool-migrator/UniV2PoolMigratorInit.sol
// SPDX-FileCopyrightText: © 2023 Dai Foundation <www.daifoundation.org>

//
// 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/>.

interface GemLike {
    function balanceOf(address) external view returns (uint256);
    function totalSupply() external view returns (uint256);
    function approve(address, uint256) external;
    function transfer(address, uint256) external;
}

interface PoolLike {
    function mint(address) external;
    function burn(address) external;
    function getReserves() external view returns (uint112, uint112, uint32);
}

interface DaiUsdsLike_0 {
    function daiToUsds(address, uint256) external;
}

interface MkrSkyLike_0 {
    function mkrToSky(address, uint256) external;
}

interface PipLike_0 {
    function read() external view returns (bytes32);
    function kiss(address) external;
    function diss(address) external;
}

library UniV2PoolMigratorInit {
    function init(
        DssInstance memory dss,
        address pairDaiMkr,
        address pairUsdsSky
    ) internal {
        // Using pProxy instead of address(this) as otherwise won't work in tests, in real execution should be same address
        address pProxy = dss.chainlog.getAddress("MCD_PAUSE_PROXY");

        require(GemLike(pairUsdsSky).totalSupply() == 0, "UniV2PoolMigratorInit/sanity-check-1-failed");

        // Sanity check for Uniswap vs oracle price. This is completely unnecessary but acts as a separate safety layer.
        {
        PipLike_0 mkrPip = PipLike_0(dss.chainlog.getAddress("PIP_MKR"));
        mkrPip.kiss(pProxy);
        uint256 pipPrice = uint256(mkrPip.read()); // Assume par is 1
        mkrPip.diss(pProxy);

        (uint256 daiReserve, uint256 mkrReserve, ) = PoolLike(pairDaiMkr).getReserves();
        uint256 uniPrice = daiReserve * 1e18 / mkrReserve;

        require(
            uniPrice < pipPrice * 102 / 100 && uniPrice > pipPrice * 98 / 100,
            "UniV2PoolMigratorInit/sanity-check-2-failed"
        );
        }

        GemLike dai = GemLike(dss.chainlog.getAddress("MCD_DAI"));
        GemLike mkr = GemLike(dss.chainlog.getAddress("MCD_GOV"));

        uint256 daiAmtPrev = dai.balanceOf(pProxy);
        uint256 mkrAmtPrev = mkr.balanceOf(pProxy);

        GemLike(pairDaiMkr).transfer(pairDaiMkr, GemLike(pairDaiMkr).balanceOf(pProxy));
        PoolLike(pairDaiMkr).burn(pProxy);

        DaiUsdsLike_0 daiUsds = DaiUsdsLike_0(dss.chainlog.getAddress("DAI_USDS"));
        MkrSkyLike_0   mkrSky = MkrSkyLike_0(dss.chainlog.getAddress("MKR_SKY"));

        uint256 daiAmt = dai.balanceOf(pProxy) - daiAmtPrev;
        uint256 mkrAmt = mkr.balanceOf(pProxy) - mkrAmtPrev;
        dai.approve(address(daiUsds), daiAmt);
        mkr.approve(address(mkrSky), mkrAmt);
        daiUsds.daiToUsds(pairUsdsSky, daiAmt);
        mkrSky.mkrToSky(pairUsdsSky, mkrAmt);
        PoolLike(pairUsdsSky).mint(pProxy);

        require(GemLike(pairUsdsSky).balanceOf(pProxy) > 0, "UniV2PoolMigratorInit/sanity-check-3-failed");
    }
}

// src/dependencies/01-usds/UsdsInit.sol
// SPDX-FileCopyrightText: © 2023 Dai Foundation <www.daifoundation.org>

//
// 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/>.

interface UsdsLike {
    function rely(address) external;
    function version() external view returns (string memory);
    function getImplementation() external view returns (address);
}

interface UsdsJoinLike_0 {
    function usds() external view returns (address);
    function vat() external view returns (address);
}

interface DaiUsdsLike_1 {
    function daiJoin() external view returns (address);
    function usdsJoin() external view returns (address);
}

library UsdsInit {

    function init(
        DssInstance memory dss,
        UsdsInstance memory instance
    ) internal {
        require(keccak256(bytes(UsdsLike(instance.usds).version())) == keccak256("1"), "UsdsInit/version-does-not-match");
        require(UsdsLike(instance.usds).getImplementation() == instance.usdsImp, "UsdsInit/imp-does-not-match");

        require(UsdsJoinLike_0(instance.usdsJoin).vat() == address(dss.vat), "UsdsInit/vat-does-not-match");
        require(UsdsJoinLike_0(instance.usdsJoin).usds() == instance.usds, "UsdsInit/usds-does-not-match");

        address daiJoin = dss.chainlog.getAddress("MCD_JOIN_DAI");
        require(DaiUsdsLike_1(instance.daiUsds).daiJoin() == daiJoin, "UsdsInit/daiJoin-does-not-match");
        require(DaiUsdsLike_1(instance.daiUsds).usdsJoin() == instance.usdsJoin, "UsdsInit/usdsJoin-does-not-match");

        UsdsLike(instance.usds).rely(instance.usdsJoin);

        dss.chainlog.setAddress("USDS",      instance.usds);
        dss.chainlog.setAddress("USDS_IMP",  instance.usdsImp);
        dss.chainlog.setAddress("USDS_JOIN", instance.usdsJoin);
        dss.chainlog.setAddress("DAI_USDS",  instance.daiUsds);
    }
}

// src/dependencies/02-susds/SUsdsInit.sol
// SPDX-FileCopyrightText: © 2023 Dai Foundation <www.daifoundation.org>

//
// 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/>.

interface SUsdsLike {
    function version() external view returns (string memory);
    function getImplementation() external view returns (address);
    function usdsJoin() external view returns (address);
    function vat() external view returns (address);
    function usds() external view returns (address);
    function vow() external view returns (address);
    function file(bytes32, uint256) external;
    function drip() external returns (uint256);
}

interface UsdsJoinLike_1 {
    function usds() external view returns (address);
}

struct SUsdsConfig {
    address usdsJoin;
    address usds;
    uint256 ssr;
}

library SUsdsInit {

    uint256 constant internal RAY                   = 10**27;
    uint256 constant internal RATES_ONE_HUNDRED_PCT = 1000000021979553151239153027;

    function init(
        DssInstance   memory dss,
        SUsdsInstance memory instance,
        SUsdsConfig   memory cfg
    ) internal {
        require(keccak256(abi.encodePacked(SUsdsLike(instance.sUsds).version())) == keccak256(abi.encodePacked("1")), "SUsdsInit/version-does-not-match");
        require(SUsdsLike(instance.sUsds).getImplementation() == instance.sUsdsImp, "SUsdsInit/imp-does-not-match");

        require(SUsdsLike(instance.sUsds).vat()      == address(dss.vat), "SUsdsInit/vat-does-not-match");
        require(SUsdsLike(instance.sUsds).usdsJoin() == cfg.usdsJoin,     "SUsdsInit/usdsJoin-does-not-match");
        require(SUsdsLike(instance.sUsds).usds()     == cfg.usds,         "SUsdsInit/usds-does-not-match");
        require(SUsdsLike(instance.sUsds).vow()      == address(dss.vow), "SUsdsInit/vow-does-not-match");

        require(cfg.ssr >= RAY && cfg.ssr <= RATES_ONE_HUNDRED_PCT, "SUsdsInit/ssr-out-of-boundaries");

        dss.vat.rely(instance.sUsds);

        SUsdsLike(instance.sUsds).drip();
        SUsdsLike(instance.sUsds).file("ssr", cfg.ssr);

        dss.chainlog.setAddress("SUSDS",     instance.sUsds);
        dss.chainlog.setAddress("SUSDS_IMP", instance.sUsdsImp);
    }
}

// src/dependencies/03-sky/SkyInit.sol
// SPDX-FileCopyrightText: © 2023 Dai Foundation <www.daifoundation.org>

//
// 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/>.

interface SkyLike {
    function rely(address) external;
}

interface MkrSkyLike_1 {
    function mkr() external view returns (address);
    function sky() external view returns (address);
    function rate() external view returns (uint256);
}

interface MkrLike {
    function authority() external view returns (address);
}

interface MkrAuthorityLike {
    function rely(address) external;
}

library SkyInit {
    function init(
        DssInstance memory dss,
        SkyInstance memory instance,
        uint256 rate
    ) internal {
        address mkr = dss.chainlog.getAddress("MCD_GOV");
        require(MkrSkyLike_1(instance.mkrSky).mkr()  == mkr,          "SkyInit/mkr-does-not-match");
        require(MkrSkyLike_1(instance.mkrSky).sky()  == instance.sky, "SkyInit/sky-does-not-match");
        require(MkrSkyLike_1(instance.mkrSky).rate() == rate,         "SkyInit/rate-does-not-match");

        SkyLike(instance.sky).rely(instance.mkrSky);
        MkrAuthorityLike(MkrLike(mkr).authority()).rely(instance.mkrSky);

        dss.chainlog.setAddress("SKY",     instance.sky);
        dss.chainlog.setAddress("MKR_SKY", instance.mkrSky);
    }
}

// src/dependencies/05-flapper/FlapperInit.sol
// SPDX-FileCopyrightText: © 2023 Dai Foundation <www.daifoundation.org>

//
// 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/>.

interface FlapperUniV2Like {
    function pip() external view returns (address);
    function spotter() external view returns (address);
    function usds() external view returns (address);
    function gem() external view returns (address);
    function receiver() external view returns (address);
    function pair() external view returns (address);
    function rely(address) external;
    function file(bytes32, uint256) external;
    function file(bytes32, address) external;
}

interface SplitterMomLike {
    function splitter() external view returns (address);
    function setAuthority(address) external;
}

interface OracleWrapperLike {
    function pip() external view returns (address);
    function divisor() external view returns (uint256);
}

interface PipLike_1 {
    function kiss(address) external;
}

interface PairLike {
    function token0() external view returns (address);
    function token1() external view returns (address);
}

interface UsdsJoinLike_2 {
    function dai() external view returns (address); // TODO: Replace when new join is ready by the new getter
}

interface SplitterLike {
    function live() external view returns (uint256);
    function vat() external view returns (address);
    function usdsJoin() external view returns (address);
    function hop() external view returns (uint256);
    function rely(address) external;
    function file(bytes32, uint256) external;
    function file(bytes32, address) external;
}

interface FarmLike {
    function rewardsToken() external view returns (address);
    function setRewardsDistribution(address) external;
    function setRewardsDuration(uint256) external;
}

struct FlapperUniV2Config {
    uint256 want;
    address pip;
    address pair;
    address usds;
    address splitter;
    bytes32 prevChainlogKey;
    bytes32 chainlogKey;
}

struct FarmConfig {
    address splitter;
    address usdsJoin;
    uint256 hop;
    bytes32 prevChainlogKey;
    bytes32 chainlogKey;
}

struct SplitterConfig {
    uint256 hump;
    uint256 bump;
    uint256 hop;
    uint256 burn;
    address usdsJoin;
    bytes32 splitterChainlogKey;
    bytes32 prevMomChainlogKey;
    bytes32 momChainlogKey;
}

library FlapperInit {
    uint256 constant WAD = 10 ** 18;
    uint256 constant RAY = 10 ** 27;

    function initFlapperUniV2(
        DssInstance        memory dss,
        address                   flapper_,
        FlapperUniV2Config memory cfg
    ) internal {
        FlapperUniV2Like flapper = FlapperUniV2Like(flapper_);

        // Sanity checks
        require(flapper.spotter()  == address(dss.spotter),                       "Flapper spotter mismatch");
        require(flapper.usds()     == cfg.usds,                                   "Flapper usds mismatch");
        require(flapper.pair()     == cfg.pair,                                   "Flapper pair mismatch");
        require(flapper.receiver() == dss.chainlog.getAddress("MCD_PAUSE_PROXY"), "Flapper receiver mismatch");

        PairLike pair = PairLike(flapper.pair());
        (address pairUsds, address pairGem) = pair.token0() == cfg.usds ? (pair.token0(), pair.token1())
                                                                        : (pair.token1(), pair.token0());
        require(pairUsds == cfg.usds,      "Usds mismatch");
        require(pairGem  == flapper.gem(), "Gem mismatch");

        require(cfg.want >= WAD * 90 / 100, "want too low");

        flapper.file("want", cfg.want);
        flapper.file("pip",  cfg.pip);
        flapper.rely(cfg.splitter);

        SplitterLike(cfg.splitter).file("flapper", flapper_);

        if (cfg.prevChainlogKey != bytes32(0)) dss.chainlog.removeAddress(cfg.prevChainlogKey);
        dss.chainlog.setAddress(cfg.chainlogKey, flapper_);
    }

    function initDirectOracle(address flapper) internal {
        PipLike_1(FlapperUniV2Like(flapper).pip()).kiss(flapper);
    }

    function initOracleWrapper(
        DssInstance memory dss,
        address wrapper_,
        uint256 divisor,
        bytes32 clKey
    ) internal {
        OracleWrapperLike wrapper = OracleWrapperLike(wrapper_);
        require(wrapper.divisor() == divisor, "Wrapper divisor mismatch"); // Sanity check
        PipLike_1(wrapper.pip()).kiss(wrapper_);
        dss.chainlog.setAddress(clKey, wrapper_);
    }

    function setFarm(
        DssInstance memory dss,
        address            farm_,
        FarmConfig  memory cfg
    ) internal {
        FarmLike     farm     = FarmLike(farm_);
        SplitterLike splitter = SplitterLike(cfg.splitter);

        require(farm.rewardsToken() == UsdsJoinLike_2(cfg.usdsJoin).dai(), "Farm rewards not usds");
        // Staking token is checked in the Lockstake script

        // The following two checks enforce the initSplitter function has to be called first
        require(cfg.hop >= 5 minutes, "hop too low");
        require(cfg.hop == splitter.hop(), "hop mismatch");

        splitter.file("farm", farm_);

        farm.setRewardsDistribution(cfg.splitter);
        farm.setRewardsDuration(cfg.hop);

        if (cfg.prevChainlogKey != bytes32(0)) dss.chainlog.removeAddress(cfg.prevChainlogKey);
        dss.chainlog.setAddress(cfg.chainlogKey, farm_);
    }

    function initSplitter(
        DssInstance      memory dss,
        SplitterInstance memory splitterInstance,
        SplitterConfig   memory cfg
    ) internal {
        SplitterLike    splitter = SplitterLike(splitterInstance.splitter);
        SplitterMomLike mom      = SplitterMomLike(splitterInstance.mom);

        // Sanity checks
        require(splitter.live()     == 1,                              "Splitter not live");
        require(splitter.vat()      == address(dss.vat),               "Splitter vat mismatch");
        require(splitter.usdsJoin() == cfg.usdsJoin,                   "Splitter usdsJoin mismatch");
        require(mom.splitter()      == splitterInstance.splitter,      "Mom splitter mismatch");

        require(cfg.hump > 0,         "hump too low");
        require(cfg.bump % RAY == 0,  "bump not multiple of RAY");
        require(cfg.hop >= 5 minutes, "hop too low");
        require(cfg.burn <= WAD,      "burn too high");

        splitter.file("hop",  cfg.hop);
        splitter.file("burn", cfg.burn);
        splitter.rely(address(mom));
        splitter.rely(address(dss.vow));

        dss.vow.file("flapper", splitterInstance.splitter);
        dss.vow.file("hump", cfg.hump);
        dss.vow.file("bump", cfg.bump);

        mom.setAuthority(dss.chainlog.getAddress("MCD_ADM"));

        dss.chainlog.setAddress(cfg.splitterChainlogKey, splitterInstance.splitter);
        if (cfg.prevMomChainlogKey != bytes32(0)) dss.chainlog.removeAddress(cfg.prevMomChainlogKey);
        dss.chainlog.setAddress(cfg.momChainlogKey, address(mom));
    }
}

// src/DssSpell.sol
// SPDX-FileCopyrightText: © 2020 Dai Foundation <www.daifoundation.org>

//
// 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/>.

// import "dss-exec-lib/DssExec.sol";

interface PauseLike {
    function delay() external view returns (uint256);
    function exec(address, bytes32, bytes calldata, uint256) external returns (bytes memory);
    function plot(address, bytes32, bytes calldata, uint256) external;
    function setDelay(uint256) external;
}

interface ChainlogLike_4 {
    function getAddress(bytes32) external view returns (address);
}

interface SpellActionLike {
    function officeHours() external view returns (bool);
    function description() external view returns (string memory);
    function nextCastTime(uint256) external view returns (uint256);
}

interface VestedRewardsDistributionLike_2 {
    function distribute() external returns (uint256 amount);
}

contract DssExec {
    ChainlogLike_4  constant public   chainlog = ChainlogLike_4(0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F);
    uint256                public   eta;
    bytes                  public   sig;
    bool                   public   done;
    bytes32      immutable public   tag;
    address      immutable public   action;
    uint256      immutable public   expiration;
    PauseLike    immutable public   pause;

    // 2024-09-17T12:00:00 UTC
    uint256       constant internal SEP_17_2024_NOON_UTC = 1726574400;
    uint256       constant public   MIN_ETA              = SEP_17_2024_NOON_UTC;

    // Provides a descriptive tag for bot consumption
    // This should be modified weekly to provide a summary of the actions
    // Hash: seth keccak -- "$(wget https://<executive-vote-canonical-post> -q -O - 2>/dev/null)"
    function description() external view returns (string memory) {
        return SpellActionLike(action).description();
    }

    function officeHours() external view returns (bool) {
        return SpellActionLike(action).officeHours();
    }

    function nextCastTime() external view returns (uint256 castTime) {
        return SpellActionLike(action).nextCastTime(eta);
    }

    // @param _description  A string description of the spell
    // @param _expiration   The timestamp this spell will expire. (Ex. block.timestamp + 30 days)
    // @param _spellAction  The address of the spell action
    constructor(uint256 _expiration, address _spellAction) {
        pause       = PauseLike(chainlog.getAddress("MCD_PAUSE"));
        expiration  = _expiration;
        action      = _spellAction;

        sig = abi.encodeWithSignature("execute()");
        bytes32 _tag;                    // Required for assembly access
        address _action = _spellAction;  // Required for assembly access
        assembly { _tag := extcodehash(_action) }
        tag = _tag;
    }

    function schedule() public {
        require(block.timestamp <= expiration, "This contract has expired");
        require(eta == 0, "This spell has already been scheduled");
        // ---------- Set earliest execution date September 17, 12:00 UTC ----------
        // Forum: https://forum.makerdao.com/t/sky-protocol-launch-season-token-and-product-launch-parameter-proposal/25031
        // Poll: https://vote.makerdao.com/polling/QmTySKwi
        // Note: In case the spell is scheduled later than planned, we have to switch back to the regular logic to respect GSM delay enforced by MCD_PAUSE
        eta = _max(block.timestamp + PauseLike(pause).delay(), MIN_ETA);
        pause.plot(action, tag, sig, eta);
    }

    function cast() public {
        require(!done, "spell-already-cast");
        done = true;
        pause.exec(action, tag, sig, eta);
    }

    function _max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }
}

contract DssSpellAction is DssAction {
    // Provides a descriptive tag for bot consumption
    // This should be modified weekly to provide a summary of the actions
    // Hash: cast keccak -- "$(wget 'https://raw.githubusercontent.com/makerdao/community/4911c55070a1f40998da1caba08bda37d6c615bb/governance/votes/Executive%20vote%20-%20September%2013%2C%202024.md' -q -O - 2>/dev/null)"
    string public constant override description =
        "2024-09-13 MakerDAO Executive Spell | Hash: 0xdf8af8066b5e0a90668ab343a1244624c58a30b568ff9113dbc82a22a77d0cf6";

    // Set office hours according to the summary
    function officeHours() public pure override returns (bool) {
        return false;
    }

    // ---------- Rates ----------
    // Many of the settings that change weekly rely on the rate accumulator
    // described at https://docs.makerdao.com/smart-contract-modules/rates-module
    // To check this yourself, use the following rate calculation (example 8%):
    //
    // $ bc -l <<< 'scale=27; e( l(1.08)/(60 * 60 * 24 * 365) )'
    //
    // A table of rates can be found at
    //    https://ipfs.io/ipfs/QmVp4mhhbwWGTfbh2BzwQB9eiBrQBKiqcPRZCaAxNUaar6
    //
    // uint256 internal constant X_PCT_RATE = ;
    uint256 internal constant SIX_PT_TWO_FIVE_PCT_RATE = 1000000001922394148741344865;

    // ---------- Math ----------
    uint256 internal constant THOUSAND = 10**3;
    uint256 internal constant MILLION  = 10**6;
    uint256 internal constant WAD      = 10**18;
    uint256 internal constant RAD      = 10**45;

    // ---------- Phase 1b Addresses ----------

    address internal constant USDS                         = 0xdC035D45d973E3EC169d2276DDab16f1e407384F;
    address internal constant USDS_IMP                     = 0x1923DfeE706A8E78157416C29cBCCFDe7cdF4102;
    address internal constant USDS_JOIN                    = 0x3C0f895007CA717Aa01c8693e59DF1e8C3777FEB;
    address internal constant DAI_USDS                     = 0x3225737a9Bbb6473CB4a45b7244ACa2BeFdB276A;
    address internal constant SUSDS                        = 0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD;
    address internal constant SUSDS_IMP                    = 0x4e7991e5C547ce825BdEb665EE14a3274f9F61e0;
    address internal constant SKY                          = 0x56072C95FAA701256059aa122697B133aDEd9279;
    address internal constant MKR_SKY                      = 0xBDcFCA946b6CDd965f99a839e4435Bcdc1bc470B;
    address internal constant UNIV2DAIMKR                  = 0x517F9dD285e75b599234F7221227339478d0FcC8;
    address internal constant UNIV2USDSSKY                 = 0x2621CC0B3F3c079c1Db0E80794AA24976F0b9e3c;
    address internal constant MCD_SPLIT                    = 0xBF7111F13386d23cb2Fba5A538107A73f6872bCF;
    address internal constant SPLITTER_MOM                 = 0xF51a075d468dE7dE3599C1Dc47F5C42d02C9230e;
    address internal constant MCD_FLAP                     = 0xc5A9CaeBA70D6974cBDFb28120C3611Dd9910355;
    address internal constant FLAP_SKY_ORACLE              = 0x38e8c1D443f546Dc014D7756ec63116161CB7B25;
    address internal constant MCD_VEST_SKY                 = 0xB313Eab3FdE99B2bB4bA9750C2DDFBe2729d1cE9;
    address internal constant REWARDS_USDS_SKY             = 0x0650CAF159C5A49f711e8169D4336ECB9b950275;
    address internal constant REWARDS_DIST_USDS_SKY        = 0x2F0C88e935Db5A60DDA73b0B4EAEef55883896d9;
    address internal constant REWARDS_USDS_01              = 0x10ab606B067C9C461d8893c47C7512472E19e2Ce;
    address internal constant CRON_REWARDS_DIST_JOB        = 0x6464C34A02DD155dd0c630CE233DD6e21C24F9A5;
    address internal constant WRAPPER_USDS_LITE_PSM_USDC_A = 0xA188EEC8F81263234dA3622A406892F3D630f98c;

    // ---------- MCD Addresses ----------
    address internal immutable MCD_PAUSE = DssExecLib.getChangelogAddress("MCD_PAUSE");

    function actions() public override {

        // Do not authorize ESM in any new contracts
        // Note: no action needed

        // Note: load the Maker Protocol contracts depencencies
        DssInstance memory dss = MCD.loadFromChainlog(DssExecLib.LOG);

        // ---------- New Tokens Init ----------
        // Forum: https://forum.makerdao.com/t/sky-protocol-launch-season-token-and-product-launch-parameter-proposal/25031
        // Poll: https://vote.makerdao.com/polling/QmTySKwi

        // Init USDS by calling UsdsInit.init with the following parameters:
        UsdsInit.init(
            // Note: Maker Protocol contracts dependencies
            dss,
            UsdsInstance({
                // Init USDS with usds parameter being 0xdC035D45d973E3EC169d2276DDab16f1e407384F
                usds: USDS,
                // Init USDS with usdsImp parameter being 0x1923DfeE706A8E78157416C29cBCCFDe7cdF4102
                usdsImp: USDS_IMP,
                // Init USDS with UsdsJoin parameter being 0x3C0f895007CA717Aa01c8693e59DF1e8C3777FEB
                usdsJoin: USDS_JOIN,
                // Init USDS with DaiUsds parameter being 0x3225737a9Bbb6473CB4a45b7244ACa2BeFdB276A
                daiUsds: DAI_USDS
            })
        );

        // Add usds to chainlog with key "USDS" via the UsdsInit.init function

        // Add usdsImp to chainlog under the key "USDS_IMP" via the UsdsInit.init function

        // Add UsdsJoin to chainlog under the key "USDS_JOIN" via the UsdsInit.init function

        // Add DaiUsds to chainlog under the key "DAI_USDS" via the UsdsInit.init function

        // The usdsJoin Adapter will be authorized in the usds contract by calling rely via the UsdsInit.init function

        // Note: the instructions above are executed through UsdsInit.init()

        // Init sUSDS by calling SUsdsInit.init with the following parameters:
        SUsdsInit.init(
            // Note: Maker Protocol contracts dependencies
            dss,
            SUsdsInstance({
                // Init sUSDS with sUsds parameter being 0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD
                sUsds: SUSDS,
                // Init sUSDS with sUsdsImp parameter being 0x4e7991e5C547ce825BdEb665EE14a3274f9F61e0
                sUsdsImp: SUSDS_IMP
            }),
            SUsdsConfig({
                // Init sUSDS with usdsJoin parameter being 0x3C0f895007CA717Aa01c8693e59DF1e8C3777FEB
                usdsJoin: USDS_JOIN,
                // Init sUSDS with usds parameter being 0xdC035D45d973E3EC169d2276DDab16f1e407384F
                usds: USDS,
                // Init sUSDS with ssr parameter being 6.25%
                ssr: SIX_PT_TWO_FIVE_PCT_RATE
            })
        );

        // Add sUsds to chainlog under the key "SUSDS" via the SUsdsInit.init function

        // Add sUsdsImp to chainlog under the key "SUSDS_IMP" via the SUsdsInit.init function

        // sUSDS will be authorized to access the vat by calling rely via the SUsdsInit.init function

        // Note: the instructions above are executed through SUsdsInit.init()

        // Init SKY by calling SkyInit.init with the following parameters:
        SkyInit.init(
            // Note: Maker Protocol contracts dependencies
            dss,
            SkyInstance({
                // Init SKY with sky parameter being 0x56072C95FAA701256059aa122697B133aDEd9279
                sky: SKY,
                // Init SKY with mkrSky parameter being 0xBDcFCA946b6CDd965f99a839e4435Bcdc1bc470B
                mkrSky: MKR_SKY
            }),
            // Init SKY with rate parameter being 24,000
            24_000
        );

        // Add sky to chainlog under the key "SKY" via the SkyInit.init function

        // Add mkrSky to chainlog under the key "MKR_SKY" via the SkyInit.init function

        // The mkrSky contract will be authorized in the sky contract by calling rely via the SkyInit.init function

        // The mkrSky contract will be authorized in the MkrAuthority contract by calling rely via the SkyInit.init function

        // Note: the instructions above are executed through SkyInit.init()

        // ---------- Pool Migration and Flapper Init ----------
        // Forum: https://forum.makerdao.com/t/sky-protocol-launch-season-token-and-product-launch-parameter-proposal/25031
        // Poll: https://vote.makerdao.com/polling/QmTySKwi

        // Migrate full DAI/MKR UniswapV2 liquidity into USDS/SKY by calling UniV2PoolMigratorInit.init with the following parameters:
        UniV2PoolMigratorInit.init(
            // Note: Maker Protocol contracts dependencies
            dss,
            // Migrate liquidity to the new pool with pairDaiMkr parameter being 0x517F9dD285e75b599234F7221227339478d0FcC8
            UNIV2DAIMKR,
            // Migrate liquidity to the new pool with pairUsdsSky parameter being 0x2621CC0B3F3c079c1Db0E80794AA24976F0b9e3c
            UNIV2USDSSKY
        );

        // Init Splitter by calling FlapperInit.initSplitter with the following parameters:
        FlapperInit.initSplitter(
            // Note: Maker Protocol contracts dependencies
            dss,
            SplitterInstance({
                // Init Splitter with splitter parameter being 0xBF7111F13386d23cb2Fba5A538107A73f6872bCF
                splitter: MCD_SPLIT,
                // Init Splitter with mom parameter being 0xF51a075d468dE7dE3599C1Dc47F5C42d02C9230e
                mom: SPLITTER_MOM
            }),
            SplitterConfig({
                // Init Splitter with hump parameter being 55M DAI
                hump: 55 * MILLION * RAD,
                // Init Splitter with bump parameter being 65,000 DAI/USDS
                bump: 65 * THOUSAND * RAD,
                // Init Splitter with hop parameter being 10,249 seconds
                hop: 10_249,
                // Init Splitter with burn parameter being 100% (1 * WAD)
                burn: 1 * WAD,
                // Init Splitter with usdsJoin parameter being 0x3C0f895007CA717Aa01c8693e59DF1e8C3777FEB
                usdsJoin: USDS_JOIN,
                // Init Splitter with splitterChainlogKey parameter being MCD_SPLIT
                splitterChainlogKey: "MCD_SPLIT",
                // Init Splitter with prevMomChainlogKey parameter being FLAPPER_MOM
                prevMomChainlogKey: "FLAPPER_MOM",
                // Init Splitter with momChainlogKey parameter being SPLITTER_MOM
                momChainlogKey: "SPLITTER_MOM"
            })
        );

        // The flapper variable in the vow will be changed by the splitter address by calling file via the initSplitter function

        // Note: the instructions above are executed through FlapperInit.initSplitter()

        // Init new Flapper by calling FlapperInit.initFlapperUniV2 with the following parameters:
        FlapperInit.initFlapperUniV2(
            // Note: Maker Protocol contracts dependencies
            dss,
            // Init new Flapper with flapper_ parameter being 0xc5A9CaeBA70D6974cBDFb28120C3611Dd9910355
            MCD_FLAP,
            FlapperUniV2Config({
                // Init new Flapper with want parameter being 98% (98 * WAD / 100)
                want: 98 * WAD / 100,
                // Init new Flapper with pip parameter being 0x38e8c1D443f546Dc014D7756ec63116161CB7B25
                pip: FLAP_SKY_ORACLE,
                // Init new Flapper with pair parameter being 0x2621CC0B3F3c079c1Db0E80794AA24976F0b9e3c
                pair: UNIV2USDSSKY,
                // Init new Flapper with usds parameter being 0xdC035D45d973E3EC169d2276DDab16f1e407384F
                usds: USDS,
                // Init new Flapper with splitter parameter being 0xBF7111F13386d23cb2Fba5A538107A73f6872bCF
                splitter: MCD_SPLIT,
                // Init new Flapper with prevChainlogKey parameter being MCD_FLAP
                prevChainlogKey: "MCD_FLAP",
                // Init new Flapper with chainlogKey parameter being MCD_FLAP
                chainlogKey: "MCD_FLAP"
            })
        );

        // Init new Oracle by calling FlapperInit.initOracleWrapper with the following parameters:
        FlapperInit.initOracleWrapper(
            // Note: Maker Protocol contracts dependencies
            dss,
            // Init new Oracle with wrapper_ parameter being 0x38e8c1D443f546Dc014D7756ec63116161CB7B25
            FLAP_SKY_ORACLE,
            // Init new Oracle with divisor parameter being 24,000
            24_000,
            // Init new Oracle with clKey parameter being FLAP_SKY_ORACLE
            "FLAP_SKY_ORACLE"
        );

        // Authorize wrapper to read MKR oracle price

        // Note: the instructions above are executed through FlapperInit.initOracleWrapper()

        // ---------- Setup DssVestMintable for SKY ----------
        // Forum: https://forum.makerdao.com/t/sky-protocol-launch-season-token-and-product-launch-parameter-proposal/25031
        // Poll: https://vote.makerdao.com/polling/QmTySKwi

        // Authorize DssVestMintable on SKY by calling DssExecLib.authorize with the following parameters:
        // Authorize DssVestMintable on SKY with _base parameter being 0x56072C95FAA701256059aa122697B133aDEd9279
        // Authorize DssVestMintable on SKY with _ward parameter being 0xB313Eab3FdE99B2bB4bA9750C2DDFBe2729d1cE9
        DssExecLib.authorize(SKY, MCD_VEST_SKY);

        // Set DssVestMintable max rate (cap) by calling DssExecLib.setValue with the following parameters:
        // Set DssVestMintable max rate (cap) with _base parameter being 0xB313Eab3FdE99B2bB4bA9750C2DDFBe2729d1cE9
        // Set DssVestMintable max rate (cap) with _what parameter being "cap"
        // Set DssVestMintable max rate (cap) with _amt parameter being 799,999,999.999999999985808000 Sky per year (800M * WAD / 365 days )
        DssExecLib.setValue(MCD_VEST_SKY, "cap", 800 * MILLION * WAD / 365 days);

        // Add DssVestMintable to Chainlog by calling DssExecLib.setChangelogAddress with the following parameters:
        // Add DssVestMintable to Chainlog with _key parameter being MCD_VEST_SKY
        // Add DssVestMintable to Chainlog with _val parameter being 0xB313Eab3FdE99B2bB4bA9750C2DDFBe2729d1cE9
        DssExecLib.setChangelogAddress("MCD_VEST_SKY", MCD_VEST_SKY);

        // ---------- USDS => SKY Farm Setup ----------

        // Init USDS -> SKY rewards by calling UsdsSkyFarmingInit.init with the following parameters:
        UsdsSkyFarmingInit.init(UsdsSkyFarmingInitParams({
            // Init USDS -> SKY rewards with usds parameter being 0xdC035D45d973E3EC169d2276DDab16f1e407384F
            usds: USDS,
            // Init USDS -> SKY rewards with sky parameter being 0x56072C95FAA701256059aa122697B133aDEd9279
            sky: SKY,
            // Init USDS -> SKY rewards with rewards parameter being 0x0650CAF159C5A49f711e8169D4336ECB9b950275
            rewards: REWARDS_USDS_SKY,
            // Init USDS -> SKY rewards with rewardsKey parameter being REWARDS_USDS_SKY
            rewardsKey: "REWARDS_USDS_SKY",
            // Init USDS -> SKY rewards with dist parameter being 0x2F0C88e935Db5A60DDA73b0B4EAEef55883896d9
            dist: REWARDS_DIST_USDS_SKY,
            // Init USDS -> SKY rewards with distKey parameter being REWARDS_DIST_USDS_SKY
            distKey: "REWARDS_DIST_USDS_SKY",
            // Init USDS -> SKY rewards with vest parameter being 0xB313Eab3FdE99B2bB4bA9750C2DDFBe2729d1cE9
            vest: MCD_VEST_SKY,
            // Init USDS -> SKY rewards with vestTot parameter being 600M * WAD
            vestTot: 600 * MILLION * WAD,
            // Init USDS -> SKY rewards with vestBgn parameter being block.timestamp - 7 days
            vestBgn: block.timestamp - 7 days,
            // Init USDS -> SKY rewards with vestTau parameter being 365 days - 1
            vestTau: 365 days - 1
        }));

        // Call distribute() in VestedRewardsDistribution contract in the spell execution
        VestedRewardsDistributionLike_2(REWARDS_DIST_USDS_SKY).distribute();

        // SKY Vesting Stream  | from 'block.timestamp - 7 days' for '365 days - 1' | 600M * WAD SKY | 0x2F0C88e935Db5A60DDA73b0B4EAEef55883896d9

        // Note: the instructions above are executed through UsdsSkyFarmingInit.init()

        // Initialize the new cron job by calling VestedRewardsDistributionJobInit.init with the following parameters:
        VestedRewardsDistributionJobInit.init(
            // Initialize cron job with job parameter being 0x6464C34A02DD155dd0c630CE233DD6e21C24F9A5
            CRON_REWARDS_DIST_JOB,
            VestedRewardsDistributionJobInitConfig({
                // Initialize cron job with cfg.jobKey parameter being CRON_REWARDS_DIST_JOB
                jobKey: "CRON_REWARDS_DIST_JOB"
            })
        );

        // Add VestedRewardsDistribution to the new cron job by calling VestedRewardsDistributionJobInit.setDist with the following parameters:
        VestedRewardsDistributionJobInit.setDist(
            // Add VestedRewardsDistribution to the new cron job with job parameter being 0x6464C34A02DD155dd0c630CE233DD6e21C24F9A5
            CRON_REWARDS_DIST_JOB,
            VestedRewardsDistributionJobSetDistConfig({
                // Add VestedRewardsDistribution to the new cron job with cfg.dist parameter being 0x2F0C88e935Db5A60DDA73b0B4EAEef55883896d9
                dist: REWARDS_DIST_USDS_SKY,
                // Add VestedRewardsDistribution to the new cron job with cfg.interval parameter being 7 days - 1 hours
                interval: 7 days - 1 hours
            })
        );

        // ---------- USDS => 01 Farm Setup ----------
        // Forum: https://forum.makerdao.com/t/sky-protocol-launch-season-token-and-product-launch-parameter-proposal/25031
        // Poll: https://vote.makerdao.com/polling/QmTySKwi

        // Init Rewards-01 by calling Usds01PreFarmingInit.init with the following parameters:
        Usds01PreFarmingInit.init(Usds01PreFarmingInitParams({
            // Init Rewards-01 with usds parameter being 0xdC035D45d973E3EC169d2276DDab16f1e407384F
            usds: USDS,
            // Init Rewards-01 with rewards parameter being 0x10ab606B067C9C461d8893c47C7512472E19e2Ce
            rewards: REWARDS_USDS_01,
            // Init Rewards-01 with rewardsKey parameter being REWARDS_USDS_01
            rewardsKey: "REWARDS_USDS_01"
        }));

        // ---------- MISC ----------
        // Forum: https://forum.makerdao.com/t/sky-protocol-launch-season-token-and-product-launch-parameter-proposal/25031
        // Poll: https://vote.makerdao.com/polling/QmTySKwi

        // Add LitePsmWrapper to the Chainlog by calling DssExecLib.setChangelogAddress with the following parameters:
        // Add LitePsmWrapper to the Chainlog with _key parameter being WRAPPER_USDS_LITE_PSM_USDC_A
        // Add LitePsmWrapper to the Chainlog with _val parameter being 0xA188EEC8F81263234dA3622A406892F3D630f98c
        DssExecLib.setChangelogAddress("WRAPPER_USDS_LITE_PSM_USDC_A", WRAPPER_USDS_LITE_PSM_USDC_A);

        // Update GSM Delay
        // Reduce GSM Delay by 14 hours, from 30 hours to 16 hours by calling MCD_PAUSE.setDelay
        PauseLike(MCD_PAUSE).setDelay(16 hours);

        // Note: bump chainlog version due to new modules being onboarded
        DssExecLib.setChangelogVersion("1.18.0");
    }
}

contract DssSpell is DssExec {
    constructor() DssExec(block.timestamp + 30 days, address(new DssSpellAction())) {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"MIN_ETA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"action","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cast","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chainlog","outputs":[{"internalType":"contract ChainlogLike_4","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"description","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"done","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eta","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"expiration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextCastTime","outputs":[{"internalType":"uint256","name":"castTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"officeHours","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[{"internalType":"contract PauseLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"schedule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tag","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"}]

6101006040523480156200001257600080fd5b50620000224262278d006200013a565b60405162000030906200012c565b604051809103906000f0801580156200004d573d6000803e3d6000fd5b506040516321f8a72160e01b8152684d43445f504155534560b81b600482015273da0ab1e0017debcd72be8599041a2aa3ba7e740f906321f8a72190602401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d0919062000162565b6001600160a01b0390811660e05260c0839052811660a0526040805160048152602481019091526020810180516001600160e01b0316631851865560e21b17905260019062000120908262000239565b503f6080525062000305565b615afa8062000e2b83390190565b808201808211156200015c57634e487b7160e01b600052601160045260246000fd5b92915050565b6000602082840312156200017557600080fd5b81516001600160a01b03811681146200018d57600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620001bf57607f821691505b602082108103620001e057634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200023457600081815260208120601f850160051c810160208610156200020f5750805b601f850160051c820191505b8181101562000230578281556001016200021b565b5050505b505050565b81516001600160401b0381111562000255576200025562000194565b6200026d81620002668454620001aa565b84620001e6565b602080601f831160018114620002a557600084156200028c5750858301515b600019600386901b1c1916600185901b17855562000230565b600085815260208120601f198616915b82811015620002d657888601518255948401946001909101908401620002b5565b5085821015620002f55787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e051610aa06200038b6000396000818161019c0152818161042a015281816105bc015261066c01526000818161012001526104ef01526000818160e1015281816102a60152818161032f015281816104570152818161069901526107350152600081816101550152818161047901526106bb0152610aa06000f3fe608060405234801561001057600080fd5b50600436106100b95760003560e01c8062a7029b146100be5780630a7a1c4d146100dc5780634665096d1461011b57806351f91066146101505780636e832f07146101775780637284e4161461018f5780638456cb591461019757806391d7a727146101be57806396d373e5146101c9578063ae8421e1146101d3578063b0604a26146101e0578063ce6f74aa146101e8578063f7992d8514610203578063fe7d47bb1461020c575b600080fd5b6100c6610214565b6040516100d39190610812565b60405180910390f35b6101037f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100d3565b6101427f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016100d3565b6101427f000000000000000000000000000000000000000000000000000000000000000081565b61017f6102a2565b60405190151581526020016100d3565b6100c661032b565b6101037f000000000000000000000000000000000000000000000000000000000000000081565b6101426366e96f4081565b6101d16103b3565b005b60025461017f9060ff1681565b6101d16104ed565b61010373da0ab1e0017debcd72be8599041a2aa3ba7e740f81565b61014260005481565b61014261071a565b6001805461022190610825565b80601f016020809104026020016040519081016040528092919081815260200182805461024d90610825565b801561029a5780601f1061026f5761010080835404028352916020019161029a565b820191906000526020600020905b81548152906001019060200180831161027d57829003601f168201915b505050505081565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636e832f076040518163ffffffff1660e01b8152600401602060405180830381865afa158015610302573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610326919061085f565b905090565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637284e4166040518163ffffffff1660e01b8152600401600060405180830381865afa15801561038b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103269190810190610911565b60025460ff16156104005760405162461bcd60e51b81526020600482015260126024820152711cdc195b1b0b585b1c9958591e4b58d85cdd60721b60448201526064015b60405180910390fd5b6002805460ff1916600190811790915560005460405163168ccd6760e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263168ccd67926104a3927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000929091600401610961565b6000604051808303816000875af11580156104c2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104ea9190810190610911565b50565b7f00000000000000000000000000000000000000000000000000000000000000004211156105595760405162461bcd60e51b8152602060048201526019602482015278151a1a5cc818dbdb9d1c9858dd081a185cc8195e1c1a5c9959603a1b60448201526064016103f7565b600054156105b75760405162461bcd60e51b815260206004820152602560248201527f54686973207370656c6c2068617320616c7265616479206265656e2073636865604482015264191d5b195960da1b60648201526084016103f7565b6106507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636a42b8f86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610618573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063c9190610a30565b6106469042610a49565b6366e96f406107a8565b60008190556040516346d2fbbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916346d2fbbb916106e6917f0000000000000000000000000000000000000000000000000000000000000000917f000000000000000000000000000000000000000000000000000000000000000091600191600401610961565b600060405180830381600087803b15801561070057600080fd5b505af1158015610714573d6000803e3d6000fd5b50505050565b60008054604051632fc3ef3b60e21b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063bf0fbcec90602401602060405180830381865afa158015610784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103269190610a30565b60008183116107b757816107b9565b825b90505b92915050565b60005b838110156107dd5781810151838201526020016107c5565b50506000910152565b600081518084526107fe8160208601602086016107c2565b601f01601f19169290920160200192915050565b6020815260006107b960208301846107e6565b600181811c9082168061083957607f821691505b60208210810361085957634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561087157600080fd5b8151801515811461088157600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b60006001600160401b03808411156108b8576108b8610888565b604051601f8501601f19908116603f011681019082821181831017156108e0576108e0610888565b816040528093508581528686860111156108f957600080fd5b6109078660208301876107c2565b5050509392505050565b60006020828403121561092357600080fd5b81516001600160401b0381111561093957600080fd5b8201601f8101841361094a57600080fd5b6109598482516020840161089e565b949350505050565b6001600160a01b03851681526020808201859052608060408301528354600091908290600181811c908281168061099957607f831692505b85831081036109b657634e487b7160e01b85526022600452602485fd5b6080880183905260a088018180156109d557600181146109eb57610a16565b60ff198616825284151560051b82019650610a16565b60008c81526020902060005b86811015610a10578154848201529085019089016109f7565b83019750505b505050505050809250505082606083015295945050505050565b600060208284031215610a4257600080fd5b5051919050565b808201808211156107bc57634e487b7160e01b600052601160045260246000fdfea2646970667358221220297f18e95ebe819d13c552d5403fbc225e999c99c43fa21d751b2e25a58575f064736f6c6343000810003360a0604081905263a16ed56f60e01b9052684d43445f504155534560b81b60a452738de6ddbcd5053d32292aaa0d2105a32d108484a663a16ed56f60c4602060405180830381865af41580156200005a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000809190620000a0565b6001600160a01b03166080523480156200009957600080fd5b50620000d2565b600060208284031215620000b357600080fd5b81516001600160a01b0381168114620000cb57600080fd5b9392505050565b608051615a0c620000ee6000396000610b5e0152615a0c6000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063614619541461005c5780636e832f07146100665780637284e4161461007a578063bf0fbcec1461008f578063f99e36bc146100b0575b600080fd5b6100646100b8565b005b604051600081526020015b60405180910390f35b610082610194565b6040516100719190615612565b6100a261009d366004615645565b6101b0565b604051908152602001610071565b61006461025a565b738de6ddbcd5053d32292aaa0d2105a32d108484a66335329d4c4260006040516001600160e01b031960e085901b16815264ffffffffff909216600483015215156024820152604401602060405180830381865af415801561011e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610142919061565e565b61018a5760405162461bcd60e51b81526020600482015260146024820152734f757473696465206f666669636520686f75727360601b60448201526064015b60405180910390fd5b61019261025a565b565b6040518060a00160405280606e8152602001615929606e913981565b600064ffffffffff8211156101c457600080fd5b6040805163692aba2b60e11b815264ffffffffff808516600483015242166024820152600060448201529051738de6ddbcd5053d32292aaa0d2105a32d108484a69163d25574569160648083019260209291908290030181865af4158015610230573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102549190615680565b92915050565b60006102736000805160206159b7833981519152610c40565b6040805160808101825273dc035d45d973e3ec169d2276ddab16f1e407384f8152731923dfee706a8e78157416c29cbccfde7cdf41026020820152733c0f895007ca717aa01c8693e59df1e8c3777feb91810191909152733225737a9bbb6473cb4a45b7244aca2befdb276a60608201529091506102f2908290610c51565b6103ab81604051806040016040528073a3931d71877c0e7a3148cb7eb4463524fec27fbd6001600160a01b03168152602001734e7991e5c547ce825bdeb665ee14a3274f9f61e06001600160a01b03168152506040518060600160405280733c0f895007ca717aa01c8693e59df1e8c3777feb6001600160a01b0316815260200173dc035d45d973e3ec169d2276ddab16f1e407384f6001600160a01b031681526020016b033b2e3cba7e3787ea046e618152506113c6565b604080518082019091527356072c95faa701256059aa122697b133aded9279815273bdcfca946b6cdd965f99a839e4435bcdc1bc470b60208201526103f4908290615dc0611b2d565b6104278173517f9dd285e75b599234f7221227339478d0fcc8732621cc0b3f3c079c1db0e80794aa24976f0b9e3c611fe4565b60408051808201825273bf7111f13386d23cb2fba5a538107a73f6872bcf815273f51a075d468de7de3599c1dc47f5c42d02c9230e60208201528151610100810190925261054891839190806d0166bb7f0435c9e717bb45005915602d1b610493620f424060376156af565b61049d91906156af565b81526020016d0166bb7f0435c9e717bb45005915602d1b6104c16103e860416156af565b6104cb91906156af565b815261280960208201526040016104eb670de0b6b3a764000060016156af565b8152733c0f895007ca717aa01c8693e59df1e8c3777feb6020820152681350d117d4d413125560ba1b60408201526a464c41505045525f4d4f4d60a81b60608201526b53504c49545445525f4d4f4d60a01b608090910152612b59565b6106158173c5a9caeba70d6974cbdfb28120c3611dd99103556040518060e001604052806064670de0b6b3a7640000606261058391906156af565b61058d91906156e4565b81527338e8c1d443f546dc014d7756ec63116161cb7b256020820152732621cc0b3f3c079c1db0e80794aa24976f0b9e3c604082015273dc035d45d973e3ec169d2276ddab16f1e407384f606082015273bf7111f13386d23cb2fba5a538107a73f6872bcf60808201526704d43445f464c41560c41b60a0820181905260c09091015261346d565b610649817338e8c1d443f546dc014d7756ec63116161cb7b25615dc06e464c41505f534b595f4f5241434c4560881b613e33565b604051632bef459560e01b81527356072c95faa701256059aa122697b133aded9279600482015273b313eab3fde99b2bb4ba9750c2ddfbe2729d1ce96024820152738de6ddbcd5053d32292aaa0d2105a32d108484a690632bef45959060440160006040518083038186803b1580156106c157600080fd5b505af41580156106d5573d6000803e3d6000fd5b50505050738de6ddbcd5053d32292aaa0d2105a32d108484a663eb3ffe9e73b313eab3fde99b2bb4ba9750c2ddfbe2729d1ce96301e13380670de0b6b3a7640000620f424061032061072791906156af565b61073191906156af565b61073b91906156e4565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526206361760ec1b6024830152604482015260640160006040518083038186803b15801561078b57600080fd5b505af415801561079f573d6000803e3d6000fd5b50506040516319d900a160e01b81526b4d43445f564553545f534b5960a01b600482015273b313eab3fde99b2bb4ba9750c2ddfbe2729d1ce96024820152738de6ddbcd5053d32292aaa0d2105a32d108484a692506319d900a1915060440160006040518083038186803b15801561081657600080fd5b505af415801561082a573d6000803e3d6000fd5b5050604080516101408101825273dc035d45d973e3ec169d2276ddab16f1e407384f81527356072c95faa701256059aa122697b133aded92796020820152730650caf159c5a49f711e8169d4336ecb9b950275918101919091526f524557415244535f555344535f534b5960801b6060820152732f0c88e935db5a60dda73b0b4eaeef55883896d9608082015274524557415244535f444953545f555344535f534b5960581b60a082015273b313eab3fde99b2bb4ba9750c2ddfbe2729d1ce960c08201526109409250905060e08101670de0b6b3a7640000610912620f42406102586156af565b61091c91906156af565b815260200161092e62093a80426156f8565b81526020016301e1337f815250613fd3565b50732f0c88e935db5a60dda73b0b4eaeef55883896d96001600160a01b031663e4fc6b6d6040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610995573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b99190615680565b506109fe736464c34a02dd155dd0c630ce233dd6e21c24f9a560405180602001604052807421a927a72fa922aba0a92229afa224a9aa2fa527a160591b815250614a3e565b610a50736464c34a02dd155dd0c630ce233dd6e21c24f9a56040518060400160405280732f0c88e935db5a60dda73b0b4eaeef55883896d96001600160a01b0316815260200162092c70815250614c30565b6040805160608101825273dc035d45d973e3ec169d2276ddab16f1e407384f81527310ab606b067c9c461d8893c47c7512472e19e2ce60208201526e524557415244535f555344535f303160881b91810191909152610aae90614c97565b6040516319d900a160e01b81527b575241505045525f555344535f4c4954455f50534d5f555344435f4160201b600482015273a188eec8f81263234da3622a406892f3d630f98c6024820152738de6ddbcd5053d32292aaa0d2105a32d108484a6906319d900a19060440160006040518083038186803b158015610b3157600080fd5b505af4158015610b45573d6000803e3d6000fd5b50506040516370bb923760e11b815261e10060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316925063e177246e9150602401600060405180830381600087803b158015610bac57600080fd5b505af1158015610bc0573d6000803e3d6000fd5b5050604051635f3a7dd760e01b81526020600482015260066024820152650312e31382e360d41b6044820152738de6ddbcd5053d32292aaa0d2105a32d108484a69250635f3a7dd7915060640160006040518083038186803b158015610c2557600080fd5b505af4158015610c39573d6000803e3d6000fd5b5050505050565b610c4861557a565b610254826151ab565b7fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc681600001516001600160a01b03166354fd4d506040518163ffffffff1660e01b8152600401600060405180830381865afa158015610cb4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cdc9190810190615721565b8051906020012014610d305760405162461bcd60e51b815260206004820152601f60248201527f55736473496e69742f76657273696f6e2d646f65732d6e6f742d6d61746368006044820152606401610181565b80602001516001600160a01b031681600001516001600160a01b031663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da491906157cd565b6001600160a01b031614610df85760405162461bcd60e51b815260206004820152601b60248201527a0aae6c8e692dcd2e85ed2dae05ac8decae65adcdee85adac2e8c6d602b1b6044820152606401610181565b81602001516001600160a01b031681604001516001600160a01b03166336569e776040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6c91906157cd565b6001600160a01b031614610ec05760405162461bcd60e51b815260206004820152601b60248201527a0aae6c8e692dcd2e85eecc2e85ac8decae65adcdee85adac2e8c6d602b1b6044820152606401610181565b80600001516001600160a01b031681604001516001600160a01b0316634cf282fb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3491906157cd565b6001600160a01b031614610f895760405162461bcd60e51b815260206004820152601c60248201527b0aae6c8e692dcd2e85eeae6c8e65ac8decae65adcdee85adac2e8c6d60231b6044820152606401610181565b81516040516321f8a72160e01b81526b4d43445f4a4f494e5f44414960a01b60048201526000916001600160a01b0316906321f8a72190602401602060405180830381865afa158015610fe0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100491906157cd565b9050806001600160a01b031682606001516001600160a01b031663c11645bc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611052573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107691906157cd565b6001600160a01b0316146110cc5760405162461bcd60e51b815260206004820152601f60248201527f55736473496e69742f6461694a6f696e2d646f65732d6e6f742d6d61746368006044820152606401610181565b81604001516001600160a01b031682606001516001600160a01b031663fa1e2e866040518163ffffffff1660e01b8152600401602060405180830381865afa15801561111c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114091906157cd565b6001600160a01b0316146111965760405162461bcd60e51b815260206004820181905260248201527f55736473496e69742f757364734a6f696e2d646f65732d6e6f742d6d617463686044820152606401610181565b815160408084015190516332fd71af60e11b81526001600160a01b03909216916365fae35e916111c8916004016157f6565b600060405180830381600087803b1580156111e257600080fd5b505af11580156111f6573d6000803e3d6000fd5b50508451845160405163ca446dd960e01b8152635553445360e01b60048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b15801561124e57600080fd5b505af1158015611262573d6000803e3d6000fd5b50508451602085015160405163ca446dd960e01b8152670555344535f494d560c41b60048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b1580156112c157600080fd5b505af11580156112d5573d6000803e3d6000fd5b50508451604085810151905163ca446dd960e01b8152682aa9a229afa527a4a760b91b60048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b15801561133557600080fd5b505af1158015611349573d6000803e3d6000fd5b50508451606085015160405163ca446dd960e01b8152674441495f5553445360c01b60048201526001600160a01b0391821660248201529116925063ca446dd991506044015b600060405180830381600087803b1580156113a957600080fd5b505af11580156113bd573d6000803e3d6000fd5b50505050505050565b604051603160f81b60208201526021016040516020818303038152906040528051906020012082600001516001600160a01b03166354fd4d506040518163ffffffff1660e01b8152600401600060405180830381865afa15801561142e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526114569190810190615721565b604051602001611466919061580a565b60405160208183030381529060405280519060200120146114c95760405162461bcd60e51b815260206004820181905260248201527f5355736473496e69742f76657273696f6e2d646f65732d6e6f742d6d617463686044820152606401610181565b81602001516001600160a01b031682600001516001600160a01b031663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa158015611519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153d91906157cd565b6001600160a01b0316146115925760405162461bcd60e51b815260206004820152601c60248201527b0a6aae6c8e692dcd2e85ed2dae05ac8decae65adcdee85adac2e8c6d60231b6044820152606401610181565b82602001516001600160a01b031682600001516001600160a01b03166336569e776040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115e2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160691906157cd565b6001600160a01b03161461165b5760405162461bcd60e51b815260206004820152601c60248201527b0a6aae6c8e692dcd2e85eecc2e85ac8decae65adcdee85adac2e8c6d60231b6044820152606401610181565b80600001516001600160a01b031682600001516001600160a01b031663fa1e2e866040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116cf91906157cd565b6001600160a01b03161461172f5760405162461bcd60e51b815260206004820152602160248201527f5355736473496e69742f757364734a6f696e2d646f65732d6e6f742d6d6174636044820152600d60fb1b6064820152608401610181565b80602001516001600160a01b031682600001516001600160a01b0316634cf282fb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561177f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a391906157cd565b6001600160a01b0316146117f95760405162461bcd60e51b815260206004820152601d60248201527f5355736473496e69742f757364732d646f65732d6e6f742d6d617463680000006044820152606401610181565b82608001516001600160a01b031682600001516001600160a01b031663626cb3c56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611849573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061186d91906157cd565b6001600160a01b0316146118c25760405162461bcd60e51b815260206004820152601c60248201527b0a6aae6c8e692dcd2e85eecdeee5ac8decae65adcdee85adac2e8c6d60231b6044820152606401610181565b676765c793fa10079d601b1b8160400151101580156118f157506b033b2e3dd0d78f60556d6583816040015111155b61193d5760405162461bcd60e51b815260206004820152601f60248201527f5355736473496e69742f7373722d6f75742d6f662d626f756e646172696573006044820152606401610181565b602083015182516040516332fd71af60e11b81526001600160a01b03909216916365fae35e9161196f916004016157f6565b600060405180830381600087803b15801561198957600080fd5b505af115801561199d573d6000803e3d6000fd5b5050505081600001516001600160a01b0316639f678cca6040518163ffffffff1660e01b81526004016020604051808303816000875af11580156119e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a099190615680565b5081516040828101519051630a6ba04560e21b81526239b9b960e91b600482015260248101919091526001600160a01b03909116906329ae811490604401600060405180830381600087803b158015611a6157600080fd5b505af1158015611a75573d6000803e3d6000fd5b50508451845160405163ca446dd960e01b815264535553445360d81b60048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b158015611ace57600080fd5b505af1158015611ae2573d6000803e3d6000fd5b50508451602085015160405163ca446dd960e01b815268053555344535f494d560bc1b60048201526001600160a01b0391821660248201529116925063ca446dd9915060440161138f565b82516040516321f8a72160e01b81526000916001600160a01b0316906321f8a72190611b5b90600401615826565b602060405180830381865afa158015611b78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9c91906157cd565b9050806001600160a01b031683602001516001600160a01b0316637e992cb86040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c0e91906157cd565b6001600160a01b031614611c615760405162461bcd60e51b815260206004820152601a6024820152790a6d6f292dcd2e85edad6e45ac8decae65adcdee85adac2e8c6d60331b6044820152606401610181565b82600001516001600160a01b031683602001516001600160a01b031663692318046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cb1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd591906157cd565b6001600160a01b031614611d285760405162461bcd60e51b815260206004820152601a6024820152790a6d6f292dcd2e85ee6d6f25ac8decae65adcdee85adac2e8c6d60331b6044820152606401610181565b8183602001516001600160a01b0316632c4e722e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8f9190615680565b14611dda5760405162461bcd60e51b815260206004820152601b60248201527a0a6d6f292dcd2e85ee4c2e8ca5ac8decae65adcdee85adac2e8c6d602b1b6044820152606401610181565b825160208401516040516332fd71af60e11b81526001600160a01b03909216916365fae35e91611e0c916004016157f6565b600060405180830381600087803b158015611e2657600080fd5b505af1158015611e3a573d6000803e3d6000fd5b50505050806001600160a01b031663bf7e214f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea091906157cd565b6001600160a01b03166365fae35e84602001516040518263ffffffff1660e01b8152600401611ecf91906157f6565b600060405180830381600087803b158015611ee957600080fd5b505af1158015611efd573d6000803e3d6000fd5b50508551855160405163ca446dd960e01b815262534b5960e81b60048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b158015611f5457600080fd5b505af1158015611f68573d6000803e3d6000fd5b50508551602086015160405163ca446dd960e01b8152664d4b525f534b5960c81b60048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b158015611fc657600080fd5b505af1158015611fda573d6000803e3d6000fd5b5050505050505050565b82516040516321f8a72160e01b81526000916001600160a01b0316906321f8a7219061201290600401615839565b602060405180830381865afa15801561202f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061205391906157cd565b9050816001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612093573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120b79190615680565b156121065760405162461bcd60e51b815260206004820152602b602482015260008051602061599783398151915260448201526a18dacb4c4b59985a5b195960aa1b6064820152608401610181565b83516040516321f8a72160e01b8152662824a82fa6a5a960c91b60048201526000916001600160a01b0316906321f8a72190602401602060405180830381865afa158015612158573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217c91906157cd565b604051633ca70a7160e21b81529091506001600160a01b0382169063f29c29c4906121ab9085906004016157f6565b600060405180830381600087803b1580156121c557600080fd5b505af11580156121d9573d6000803e3d6000fd5b505050506000816001600160a01b03166357de26a46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561221d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122419190615680565b6040516332e2673d60e11b81529091506001600160a01b038316906365c4ce7a906122709086906004016157f6565b600060405180830381600087803b15801561228a57600080fd5b505af115801561229e573d6000803e3d6000fd5b50505050600080866001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156122e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123079190615870565b506001600160701b03918216935016905060008161232d84670de0b6b3a76400006156af565b61233791906156e4565b905060646123468560666156af565b61235091906156e4565b81108015612373575060646123668560626156af565b61237091906156e4565b81115b6123c15760405162461bcd60e51b815260206004820152602b602482015260008051602061599783398151915260448201526a18dacb4c8b59985a5b195960aa1b6064820152608401610181565b505086516040516321f8a72160e01b8152664d43445f44414960c81b6004820152600094506001600160a01b0390911692506321f8a7219150602401602060405180830381865afa15801561241a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243e91906157cd565b9050600085600001516001600160a01b03166321f8a7216040518163ffffffff1660e01b815260040161247090615826565b602060405180830381865afa15801561248d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b191906157cd565b90506000826001600160a01b03166370a08231856040518263ffffffff1660e01b81526004016124e191906157f6565b602060405180830381865afa1580156124fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125229190615680565b90506000826001600160a01b03166370a08231866040518263ffffffff1660e01b815260040161255291906157f6565b602060405180830381865afa15801561256f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125939190615680565b9050866001600160a01b031663a9059cbb88896001600160a01b03166370a08231896040518263ffffffff1660e01b81526004016125d191906157f6565b602060405180830381865afa1580156125ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126129190615680565b6040518363ffffffff1660e01b815260040161262f9291906158c0565b600060405180830381600087803b15801561264957600080fd5b505af115801561265d573d6000803e3d6000fd5b505060405163226bf2d160e21b81526001600160a01b038a1692506389afcb44915061268d9088906004016157f6565b600060405180830381600087803b1580156126a757600080fd5b505af11580156126bb573d6000803e3d6000fd5b505089516040516321f8a72160e01b8152674441495f5553445360c01b6004820152600093506001600160a01b0390911691506321f8a72190602401602060405180830381865afa158015612714573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273891906157cd565b89516040516321f8a72160e01b8152664d4b525f534b5960c81b60048201529192506000916001600160a01b03909116906321f8a72190602401602060405180830381865afa15801561278f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127b391906157cd565b9050600084876001600160a01b03166370a082318a6040518263ffffffff1660e01b81526004016127e491906157f6565b602060405180830381865afa158015612801573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128259190615680565b61282f91906156f8565b9050600084876001600160a01b03166370a082318b6040518263ffffffff1660e01b815260040161286091906157f6565b602060405180830381865afa15801561287d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a19190615680565b6128ab91906156f8565b60405163095ea7b360e01b81529091506001600160a01b0389169063095ea7b3906128dc90879086906004016158c0565b600060405180830381600087803b1580156128f657600080fd5b505af115801561290a573d6000803e3d6000fd5b505060405163095ea7b360e01b81526001600160a01b038a16925063095ea7b3915061293c90869085906004016158c0565b600060405180830381600087803b15801561295657600080fd5b505af115801561296a573d6000803e3d6000fd5b50506040516379603d5760e11b81526001600160a01b038716925063f2c07aae915061299c908d9086906004016158c0565b600060405180830381600087803b1580156129b657600080fd5b505af11580156129ca573d6000803e3d6000fd5b50506040516355c4b02d60e11b81526001600160a01b038616925063ab89605a91506129fc908d9085906004016158c0565b600060405180830381600087803b158015612a1657600080fd5b505af1158015612a2a573d6000803e3d6000fd5b50506040516335313c2160e11b81526001600160a01b038d169250636a6278429150612a5a908c906004016157f6565b600060405180830381600087803b158015612a7457600080fd5b505af1158015612a88573d6000803e3d6000fd5b50506040516370a0823160e01b8152600092506001600160a01b038d1691506370a0823190612abb908d906004016157f6565b602060405180830381865afa158015612ad8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612afc9190615680565b11612b4b5760405162461bcd60e51b815260206004820152602b602482015260008051602061599783398151915260448201526a18dacb4ccb59985a5b195960aa1b6064820152608401610181565b505050505050505050505050565b81516020808401516040805163255ea96360e21b8152905191926001600160a01b0385169263957aa58c9260048082019392918290030181865afa158015612ba5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc99190615680565b600114612c0c5760405162461bcd60e51b815260206004820152601160248201527053706c6974746572206e6f74206c69766560781b6044820152606401610181565b84602001516001600160a01b0316826001600160a01b03166336569e776040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7c91906157cd565b6001600160a01b031614612cca5760405162461bcd60e51b81526020600482015260156024820152740a6e0d8d2e8e8cae440ecc2e840dad2e6dac2e8c6d605b1b6044820152606401610181565b82608001516001600160a01b0316826001600160a01b031663fa1e2e866040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d3a91906157cd565b6001600160a01b031614612d8d5760405162461bcd60e51b815260206004820152601a6024820152790a6e0d8d2e8e8cae440eae6c8e694ded2dc40dad2e6dac2e8c6d60331b6044820152606401610181565b83600001516001600160a01b0316816001600160a01b0316633cd8045e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612dd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dfd91906157cd565b6001600160a01b031614612e4b5760405162461bcd60e51b815260206004820152601560248201527409adeda40e6e0d8d2e8e8cae440dad2e6dac2e8c6d605b1b6044820152606401610181565b8251612e885760405162461bcd60e51b815260206004820152600c60248201526b68756d7020746f6f206c6f7760a01b6044820152606401610181565b676765c793fa10079d601b1b8360200151612ea391906158d9565b15612eeb5760405162461bcd60e51b815260206004820152601860248201527762756d70206e6f74206d756c7469706c65206f662052415960401b6044820152606401610181565b61012c83604001511015612f2f5760405162461bcd60e51b815260206004820152600b60248201526a686f7020746f6f206c6f7760a81b6044820152606401610181565b670de0b6b3a764000083606001511115612f7b5760405162461bcd60e51b815260206004820152600d60248201526c0c4eae4dc40e8dede40d0d2ced609b1b6044820152606401610181565b6040838101519051630a6ba04560e21b8152620686f760ec1b600482015260248101919091526001600160a01b038316906329ae811490604401600060405180830381600087803b158015612fcf57600080fd5b505af1158015612fe3573d6000803e3d6000fd5b505050506060830151604051630a6ba04560e21b815263313ab93760e11b600482015260248101919091526001600160a01b038316906329ae811490604401600060405180830381600087803b15801561303c57600080fd5b505af1158015613050573d6000803e3d6000fd5b50506040516332fd71af60e11b81526001600160a01b03851692506365fae35e91506130809084906004016157f6565b600060405180830381600087803b15801561309a57600080fd5b505af11580156130ae573d6000803e3d6000fd5b50505060808601516040516332fd71af60e11b81526001600160a01b03851692506365fae35e916130e1916004016157f6565b600060405180830381600087803b1580156130fb57600080fd5b505af115801561310f573d6000803e3d6000fd5b505050506080850151845160405163d4e8be8360e01b81526001600160a01b039092169163d4e8be8391613145916004016158ed565b600060405180830381600087803b15801561315f57600080fd5b505af1158015613173573d6000803e3d6000fd5b5050505060808501518351604051630a6ba04560e21b815263068756d760e41b600482015260248101919091526001600160a01b03909116906329ae811490604401600060405180830381600087803b1580156131cf57600080fd5b505af11580156131e3573d6000803e3d6000fd5b50505060808601516020850151604051630a6ba04560e21b815263062756d760e41b600482015260248101919091526001600160a01b0390911691506329ae811490604401600060405180830381600087803b15801561324257600080fd5b505af1158015613256573d6000803e3d6000fd5b505086516040516321f8a72160e01b8152664d43445f41444d60c81b60048201526001600160a01b038581169450637a9e5e4b9350909116906321f8a72190602401602060405180830381865afa1580156132b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d991906157cd565b6040518263ffffffff1660e01b81526004016132f591906157f6565b600060405180830381600087803b15801561330f57600080fd5b505af1158015613323573d6000803e3d6000fd5b5050865160a0860151875160405163ca446dd960e01b81526001600160a01b03909316945063ca446dd9935061335b92600401615911565b600060405180830381600087803b15801561337557600080fd5b505af1158015613389573d6000803e3d6000fd5b5050505060c08301511561340057845160c0840151604051634fd7b7db60e11b81526001600160a01b0390921691639faf6fb6916133cd9160040190815260200190565b600060405180830381600087803b1580156133e757600080fd5b505af11580156133fb573d6000803e3d6000fd5b505050505b845160e084015160405163ca446dd960e01b81526001600160a01b039092169163ca446dd991613434918590600401615911565b600060405180830381600087803b15801561344e57600080fd5b505af1158015613462573d6000803e3d6000fd5b505050505050505050565b60008290508361010001516001600160a01b0316816001600160a01b0316632e77468d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134e391906157cd565b6001600160a01b0316146135345760405162461bcd60e51b815260206004820152601860248201527708cd8c2e0e0cae440e6e0dee8e8cae440dad2e6dac2e8c6d60431b6044820152606401610181565b81606001516001600160a01b0316816001600160a01b0316634cf282fb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135a491906157cd565b6001600160a01b0316146135f25760405162461bcd60e51b815260206004820152601560248201527408cd8c2e0e0cae440eae6c8e640dad2e6dac2e8c6d605b1b6044820152606401610181565b81604001516001600160a01b0316816001600160a01b031663a8aa1b316040518163ffffffff1660e01b8152600401602060405180830381865afa15801561363e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061366291906157cd565b6001600160a01b0316146136b05760405162461bcd60e51b815260206004820152601560248201527408cd8c2e0e0cae440e0c2d2e440dad2e6dac2e8c6d605b1b6044820152606401610181565b83516040516321f8a72160e01b81526001600160a01b03909116906321f8a721906136dd90600401615839565b602060405180830381865afa1580156136fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371e91906157cd565b6001600160a01b0316816001600160a01b031663f7260d3e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613765573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061378991906157cd565b6001600160a01b0316146137db5760405162461bcd60e51b815260206004820152601960248201527808cd8c2e0e0cae440e4cac6cad2eccae440dad2e6dac2e8c6d603b1b6044820152606401610181565b6000816001600160a01b031663a8aa1b316040518163ffffffff1660e01b8152600401602060405180830381865afa15801561381b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061383f91906157cd565b905060008084606001516001600160a01b0316836001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015613890573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138b491906157cd565b6001600160a01b03161461398b57826001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015613900573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061392491906157cd565b836001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015613962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061398691906157cd565b613a4f565b826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa1580156139c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139ed91906157cd565b836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015613a2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a4f91906157cd565b9150915084606001516001600160a01b0316826001600160a01b031614613aa85760405162461bcd60e51b815260206004820152600d60248201526c0aae6c8e640dad2e6dac2e8c6d609b1b6044820152606401610181565b836001600160a01b0316637bd2bea76040518163ffffffff1660e01b8152600401602060405180830381865afa158015613ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b0a91906157cd565b6001600160a01b0316816001600160a01b031614613b595760405162461bcd60e51b815260206004820152600c60248201526b08ecada40dad2e6dac2e8c6d60a31b6044820152606401610181565b6064613b6e670de0b6b3a7640000605a6156af565b613b7891906156e4565b85511015613bb75760405162461bcd60e51b815260206004820152600c60248201526b77616e7420746f6f206c6f7760a01b6044820152606401610181565b8451604051630a6ba04560e21b8152631dd85b9d60e21b600482015260248101919091526001600160a01b038516906329ae811490604401600060405180830381600087803b158015613c0957600080fd5b505af1158015613c1d573d6000803e3d6000fd5b50505050602085015160405163d4e8be8360e01b81526207069760ec1b60048201526001600160a01b0391821660248201529085169063d4e8be8390604401600060405180830381600087803b158015613c7657600080fd5b505af1158015613c8a573d6000803e3d6000fd5b50505060808601516040516332fd71af60e11b81526001600160a01b03871692506365fae35e91613cbd916004016157f6565b600060405180830381600087803b158015613cd757600080fd5b505af1158015613ceb573d6000803e3d6000fd5b5050505084608001516001600160a01b031663d4e8be83876040518263ffffffff1660e01b8152600401613d1f91906158ed565b600060405180830381600087803b158015613d3957600080fd5b505af1158015613d4d573d6000803e3d6000fd5b5050505060a085015115613dc457865160a0860151604051634fd7b7db60e11b81526001600160a01b0390921691639faf6fb691613d919160040190815260200190565b600060405180830381600087803b158015613dab57600080fd5b505af1158015613dbf573d6000803e3d6000fd5b505050505b865160c086015160405163ca446dd960e01b81526001600160a01b039092169163ca446dd991613df8918a90600401615911565b600060405180830381600087803b158015613e1257600080fd5b505af1158015613e26573d6000803e3d6000fd5b5050505050505050505050565b600083905082816001600160a01b0316631f2dc5ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613e77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e9b9190615680565b14613ee35760405162461bcd60e51b81526020600482015260186024820152770aee4c2e0e0cae440c8d2ecd2e6dee440dad2e6dac2e8c6d60431b6044820152606401610181565b806001600160a01b031663d741e2f96040518163ffffffff1660e01b8152600401602060405180830381865afa158015613f21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f4591906157cd565b6001600160a01b031663f29c29c4856040518263ffffffff1660e01b8152600401613f7091906157f6565b600060405180830381600087803b158015613f8a57600080fd5b505af1158015613f9e573d6000803e3d6000fd5b5050865160405163ca446dd960e01b81526001600160a01b03909116925063ca446dd991506134349085908890600401615911565b60408051602081019091526000815281602001516001600160a01b03168260c001516001600160a01b0316637bd2bea76040518163ffffffff1660e01b8152600401602060405180830381865afa158015614032573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061405691906157cd565b6001600160a01b0316146140b85760405162461bcd60e51b8152602060048201526024808201527f55736473536b794661726d696e67496e69742f766573742d67656d2d6d69736d6044820152630c2e8c6d60e31b6064820152608401610181565b81600001516001600160a01b031682604001516001600160a01b03166372f702f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015614108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061412c91906157cd565b6001600160a01b03161461419c5760405162461bcd60e51b815260206004820152603160248201527f55736473536b794661726d696e67496e69742f726577617264732d7374616b696044820152700dcce5ae8ded6cadc5adad2e6dac2e8c6d607b1b6064820152608401610181565b81602001516001600160a01b031682604001516001600160a01b031663d1af0c7d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156141ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061421091906157cd565b6001600160a01b0316146142805760405162461bcd60e51b815260206004820152603160248201527f55736473536b794661726d696e67496e69742f726577617264732d72657761726044820152700c8e65ae8ded6cadc5adad2e6dac2e8c6d607b1b6064820152608401610181565b81604001516001600160a01b0316637b0a47ee6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156142c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142e69190615680565b156143435760405162461bcd60e51b815260206004820152602760248201527f55736473536b794661726d696e67496e69742f7265776172642d726174652d6e6044820152666f742d7a65726f60c81b6064820152608401610181565b60006001600160a01b031682604001516001600160a01b0316633fc6df6e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015614390573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143b491906157cd565b6001600160a01b0316146144265760405162461bcd60e51b815260206004820152603360248201527f55736473536b794661726d696e67496e69742f726577617264732d64697374726044820152721a589d5d1a5bdb8b585b1c9958591e4b5cd95d606a1b6064820152608401610181565b6040516321f8a72160e01b81526000805160206159b7833981519152906321f8a7219061445590600401615839565b602060405180830381865afa158015614472573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061449691906157cd565b6001600160a01b031682604001516001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156144e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061450591906157cd565b6001600160a01b03161461455b5760405162461bcd60e51b815260206004820181905260248201527f55736473536b794661726d696e67496e69742f696e76616c69642d6f776e65726044820152606401610181565b81602001516001600160a01b031682608001516001600160a01b0316637bd2bea76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156145ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145cf91906157cd565b6001600160a01b0316146146315760405162461bcd60e51b8152602060048201526024808201527f55736473536b794661726d696e67496e69742f646973742d67656d2d6d69736d6044820152630c2e8c6d60e31b6064820152608401610181565b8160c001516001600160a01b031682608001516001600160a01b0316637bd399db6040518163ffffffff1660e01b8152600401602060405180830381865afa158015614681573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146a591906157cd565b6001600160a01b03161461470d5760405162461bcd60e51b815260206004820152602960248201527f55736473536b794661726d696e67496e69742f646973742d6473732d7665737460448201526805adad2e6dac2e8c6d60bb1b6064820152608401610181565b81604001516001600160a01b031682608001516001600160a01b03166364b87a706040518163ffffffff1660e01b8152600401602060405180830381865afa15801561475d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061478191906157cd565b6001600160a01b0316146147f05760405162461bcd60e51b815260206004820152603060248201527f55736473536b794661726d696e67496e69742f646973742d7374616b696e672d60448201526f0e4caeec2e4c8e65adad2e6dac2e8c6d60831b6064820152608401610181565b602082015160c083015160405163bf353dbb60e01b81526001600160a01b039092169163bf353dbb91614825916004016157f6565b602060405180830381865afa158015614842573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148669190615680565b6001146148c65760405162461bcd60e51b815260206004820152602860248201527f55736473536b794661726d696e67496e69742f6d697373696e672d736b792d72604482015267195b1e4b5d995cdd60c21b6064820152608401610181565b6148ef8260400151604051806020016040528085608001516001600160a01b031681525061538d565b60006149418360c001516040518060a0016040528086608001516001600160a01b031681526020018660e0015181526020018661010001518152602001866101200151815260200160008152506153ba565b905061495f83608001516040518060200160405280848152506154c3565b8082526060830151604080850151905163ca446dd960e01b81526000805160206159b78339815191529263ca446dd99261499b92600401615911565b600060405180830381600087803b1580156149b557600080fd5b505af11580156149c9573d6000803e3d6000fd5b5050505060a0830151608084015160405163ca446dd960e01b81526000805160206159b78339815191529263ca446dd992614a0692600401615911565b600060405180830381600087803b158015614a2057600080fd5b505af1158015614a34573d6000803e3d6000fd5b5050505050919050565b6040516321f8a72160e01b81526d21a927a72fa9a2a8aaa2a721a2a960911b60048201526000906000805160206159b7833981519152906321f8a72190602401602060405180830381865afa158015614a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614abf91906157cd565b9050806001600160a01b0316836001600160a01b0316635c1bba386040518163ffffffff1660e01b8152600401602060405180830381865afa158015614b09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b2d91906157cd565b6001600160a01b031614614b9e5760405162461bcd60e51b815260206004820152603260248201527f56657374656452657761726473446973747269627574696f6e4a6f62496e697460448201527117b4b73b30b634b216b9b2b8bab2b731b2b960711b6064820152608401610181565b60405163314662af60e21b81526001600160a01b0382169063c5198abc90614bca9086906004016157f6565b600060405180830381600087803b158015614be457600080fd5b505af1158015614bf8573d6000803e3d6000fd5b5050835160405163ca446dd960e01b81526000805160206159b7833981519152935063ca446dd9925061138f91908790600401615911565b80516020820151604051630704bb0560e31b81526001600160a01b03851692633825d82892614c61926004016158c0565b600060405180830381600087803b158015614c7b57600080fd5b505af1158015614c8f573d6000803e3d6000fd5b505050505050565b80600001516001600160a01b031681602001516001600160a01b03166372f702f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015614ce7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614d0b91906157cd565b6001600160a01b031614614d7d5760405162461bcd60e51b815260206004820152603360248201527f5573647330315072654661726d696e67496e69742f726577617264732d7374616044820152720d6d2dcce5ae8ded6cadc5adad2e6dac2e8c6d606b1b6064820152608401610181565b60006001600160a01b031681602001516001600160a01b031663d1af0c7d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015614dca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614dee91906157cd565b6001600160a01b031614614e575760405162461bcd60e51b815260206004820152602a60248201527f5573647330315072654661726d696e67496e69742f696e76616c69642d72657760448201526930b9323996ba37b5b2b760b11b6064820152608401610181565b80602001516001600160a01b0316637b0a47ee6040518163ffffffff1660e01b8152600401602060405180830381865afa158015614e99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ebd9190615680565b15614f1c5760405162461bcd60e51b815260206004820152602960248201527f5573647330315072654661726d696e67496e69742f7265776172642d726174656044820152682d6e6f742d7a65726f60b81b6064820152608401610181565b60006001600160a01b031681602001516001600160a01b0316633fc6df6e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015614f69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f8d91906157cd565b6001600160a01b0316146150015760405162461bcd60e51b815260206004820152603560248201527f5573647330315072654661726d696e67496e69742f726577617264732d6469736044820152741d1c9a589d5d1a5bdb8b585b1c9958591e4b5cd95d605a1b6064820152608401610181565b6040516321f8a72160e01b81526000805160206159b7833981519152906321f8a7219061503090600401615839565b602060405180830381865afa15801561504d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061507191906157cd565b6001600160a01b031681602001516001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156150bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150e091906157cd565b6001600160a01b0316146151415760405162461bcd60e51b815260206004820152602260248201527f5573647330315072654661726d696e67496e69742f696e76616c69642d6f776e60448201526132b960f11b6064820152608401610181565b6040808201516020830151915163ca446dd960e01b81526000805160206159b78339815191529263ca446dd99261517d92909190600401615911565b600060405180830381600087803b15801561519757600080fd5b505af1158015610c39573d6000803e3d6000fd5b6151b361557a565b6001600160a01b03821681526151d381661350d117d5905560ca1b615502565b6001600160a01b031660208201526151fa816b4d43445f4a4f494e5f44414960a01b615502565b6001600160a01b0316604082015261521c81664d43445f44414960c81b615502565b6001600160a01b0316606082015261523e81664d43445f564f5760c81b615502565b6001600160a01b0316608082015261526081664d43445f444f4760c81b615502565b6001600160a01b031660a082015261528281661350d117d413d560ca1b615502565b6001600160a01b031660c08201526152a481664d43445f4a554760c81b615502565b6001600160a01b031660e08201526152c781671350d117d4d413d560c21b615502565b6001600160a01b03166101008201526152ea81661350d117d1539160ca1b615502565b6001600160a01b031661012082015261530e81674d43445f4355524560c01b615502565b6001600160a01b0316610140820152615332816704d43445f464c41560c41b615502565b6001600160a01b0316610160820152615356816704d43445f464c4f560c41b615502565b6001600160a01b031661018082015261537981664d43445f45534d60c81b615502565b6001600160a01b03166101a0820152919050565b8051604051631976214360e01b81526001600160a01b03841691631976214391614c6191906004016157f6565b8051602082015160408084015160608501516080860151925163db64ff8f60e01b81526001600160a01b0395861660048201526024810194909452604484019190915260648301526084820152600060a482018190529184169063db64ff8f9060c4016020604051808303816000875af115801561543c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906154609190615680565b604051633c433d5f60e01b8152600481018290529091506001600160a01b03841690633c433d5f90602401600060405180830381600087803b1580156154a557600080fd5b505af11580156154b9573d6000803e3d6000fd5b5050505092915050565b8051604051630a6ba04560e21b8152651d995cdd125960d21b600482015260248101919091526001600160a01b038316906329ae811490604401614c61565b81516040516321f8a72160e01b8152600481018390526000916001600160a01b0316906321f8a72190602401602060405180830381865afa925050508015615567575060408051601f3d908101601f19168201909252615564918101906157cd565b60015b61557357506000610254565b9392505050565b604080516101c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081019190915290565b60005b838110156156095781810151838201526020016155f1565b50506000910152565b60208152600082518060208401526156318160408501602087016155ee565b601f01601f19169190910160400192915050565b60006020828403121561565757600080fd5b5035919050565b60006020828403121561567057600080fd5b8151801515811461557357600080fd5b60006020828403121561569257600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156156c9576156c9615699565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826156f3576156f36156ce565b500490565b8181038181111561025457610254615699565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561573357600080fd5b81516001600160401b038082111561574a57600080fd5b818401915084601f83011261575e57600080fd5b8151818111156157705761577061570b565b604051601f8201601f19908116603f011681019083821181831017156157985761579861570b565b816040528281528760208487010111156157b157600080fd5b6157c28360208301602088016155ee565b979650505050505050565b6000602082840312156157df57600080fd5b81516001600160a01b038116811461557357600080fd5b6001600160a01b0391909116815260200190565b6000825161581c8184602087016155ee565b9190910192915050565b6626a1a22fa3a7ab60c91b815260200190565b6e4d43445f50415553455f50524f585960881b815260200190565b80516001600160701b038116811461586b57600080fd5b919050565b60008060006060848603121561588557600080fd5b61588e84615854565b925061589c60208501615854565b9150604084015163ffffffff811681146158b557600080fd5b809150509250925092565b6001600160a01b03929092168252602082015260400190565b6000826158e8576158e86156ce565b500690565b66333630b83832b960c91b81526001600160a01b0391909116602082015260400190565b9182526001600160a01b031660208201526040019056fe323032342d30392d3133204d616b657244414f20457865637574697665205370656c6c207c20486173683a20307864663861663830363662356530613930363638616233343361313234343632346335386133306235363866663931313364626338326132326137376430636636556e695632506f6f6c4d69677261746f72496e69742f73616e6974792d636865000000000000000000000000da0ab1e0017debcd72be8599041a2aa3ba7e740fa264697066735822122005c844bebe2f4b902a2272c81caf4bbaa4e573e5589fbc2f8aaa8d20f258a27564736f6c63430008100033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100b95760003560e01c8062a7029b146100be5780630a7a1c4d146100dc5780634665096d1461011b57806351f91066146101505780636e832f07146101775780637284e4161461018f5780638456cb591461019757806391d7a727146101be57806396d373e5146101c9578063ae8421e1146101d3578063b0604a26146101e0578063ce6f74aa146101e8578063f7992d8514610203578063fe7d47bb1461020c575b600080fd5b6100c6610214565b6040516100d39190610812565b60405180910390f35b6101037f000000000000000000000000faf49e5b5485f3b1a260cde08891111dce5b9ae481565b6040516001600160a01b0390911681526020016100d3565b6101427f00000000000000000000000000000000000000000000000000000000670ba4e781565b6040519081526020016100d3565b6101427f17eaaf6fc5b84ee7b135f902f19d761b02ab8e3915ac41587c8f562e5ca8e39881565b61017f6102a2565b60405190151581526020016100d3565b6100c661032b565b6101037f000000000000000000000000be286431454714f511008713973d3b053a2d38f381565b6101426366e96f4081565b6101d16103b3565b005b60025461017f9060ff1681565b6101d16104ed565b61010373da0ab1e0017debcd72be8599041a2aa3ba7e740f81565b61014260005481565b61014261071a565b6001805461022190610825565b80601f016020809104026020016040519081016040528092919081815260200182805461024d90610825565b801561029a5780601f1061026f5761010080835404028352916020019161029a565b820191906000526020600020905b81548152906001019060200180831161027d57829003601f168201915b505050505081565b60007f000000000000000000000000faf49e5b5485f3b1a260cde08891111dce5b9ae46001600160a01b0316636e832f076040518163ffffffff1660e01b8152600401602060405180830381865afa158015610302573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610326919061085f565b905090565b60607f000000000000000000000000faf49e5b5485f3b1a260cde08891111dce5b9ae46001600160a01b0316637284e4166040518163ffffffff1660e01b8152600401600060405180830381865afa15801561038b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103269190810190610911565b60025460ff16156104005760405162461bcd60e51b81526020600482015260126024820152711cdc195b1b0b585b1c9958591e4b58d85cdd60721b60448201526064015b60405180910390fd5b6002805460ff1916600190811790915560005460405163168ccd6760e01b81526001600160a01b037f000000000000000000000000be286431454714f511008713973d3b053a2d38f3169263168ccd67926104a3927f000000000000000000000000faf49e5b5485f3b1a260cde08891111dce5b9ae4927f17eaaf6fc5b84ee7b135f902f19d761b02ab8e3915ac41587c8f562e5ca8e398929091600401610961565b6000604051808303816000875af11580156104c2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104ea9190810190610911565b50565b7f00000000000000000000000000000000000000000000000000000000670ba4e74211156105595760405162461bcd60e51b8152602060048201526019602482015278151a1a5cc818dbdb9d1c9858dd081a185cc8195e1c1a5c9959603a1b60448201526064016103f7565b600054156105b75760405162461bcd60e51b815260206004820152602560248201527f54686973207370656c6c2068617320616c7265616479206265656e2073636865604482015264191d5b195960da1b60648201526084016103f7565b6106507f000000000000000000000000be286431454714f511008713973d3b053a2d38f36001600160a01b0316636a42b8f86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610618573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063c9190610a30565b6106469042610a49565b6366e96f406107a8565b60008190556040516346d2fbbb60e01b81526001600160a01b037f000000000000000000000000be286431454714f511008713973d3b053a2d38f316916346d2fbbb916106e6917f000000000000000000000000faf49e5b5485f3b1a260cde08891111dce5b9ae4917f17eaaf6fc5b84ee7b135f902f19d761b02ab8e3915ac41587c8f562e5ca8e39891600191600401610961565b600060405180830381600087803b15801561070057600080fd5b505af1158015610714573d6000803e3d6000fd5b50505050565b60008054604051632fc3ef3b60e21b815260048101919091527f000000000000000000000000faf49e5b5485f3b1a260cde08891111dce5b9ae46001600160a01b03169063bf0fbcec90602401602060405180830381865afa158015610784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103269190610a30565b60008183116107b757816107b9565b825b90505b92915050565b60005b838110156107dd5781810151838201526020016107c5565b50506000910152565b600081518084526107fe8160208601602086016107c2565b601f01601f19169290920160200192915050565b6020815260006107b960208301846107e6565b600181811c9082168061083957607f821691505b60208210810361085957634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561087157600080fd5b8151801515811461088157600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b60006001600160401b03808411156108b8576108b8610888565b604051601f8501601f19908116603f011681019082821181831017156108e0576108e0610888565b816040528093508581528686860111156108f957600080fd5b6109078660208301876107c2565b5050509392505050565b60006020828403121561092357600080fd5b81516001600160401b0381111561093957600080fd5b8201601f8101841361094a57600080fd5b6109598482516020840161089e565b949350505050565b6001600160a01b03851681526020808201859052608060408301528354600091908290600181811c908281168061099957607f831692505b85831081036109b657634e487b7160e01b85526022600452602485fd5b6080880183905260a088018180156109d557600181146109eb57610a16565b60ff198616825284151560051b82019650610a16565b60008c81526020902060005b86811015610a10578154848201529085019089016109f7565b83019750505b505050505050809250505082606083015295945050505050565b600060208284031215610a4257600080fd5b5051919050565b808201808211156107bc57634e487b7160e01b600052601160045260246000fdfea2646970667358221220297f18e95ebe819d13c552d5403fbc225e999c99c43fa21d751b2e25a58575f064736f6c63430008100033

Libraries Used


Deployed Bytecode Sourcemap

247264:121:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;224917:35;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;225044:38;;;;;;;;-1:-1:-1;;;;;1084:32:1;;;1066:51;;1054:2;1039:18;225044:38:0;920:203:1;225089:42:0;;;;;;;;1274:25:1;;;1262:2;1247:18;225089:42:0;1128:177:1;225002:35:0;;;;;225733:115;;;:::i;:::-;;;1657:14:1;;1650:22;1632:41;;1620:2;1605:18;225733:115:0;1492:187:1;225601:124:0;;;:::i;225138:37::-;;;;;225288:75;;225271:10;225288:75;;227442:144;;;:::i;:::-;;224959:36;;;;;;;;;226706:728;;;:::i;224765:103::-;;224825:42;224765:103;;224875:35;;;;;;225856:132;;;:::i;224917:35::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;225733:115::-;225779:4;225819:6;-1:-1:-1;;;;;225803:35:0;;:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;225796:44;;225733:115;:::o;225601:124::-;225647:13;225696:6;-1:-1:-1;;;;;225680:35:0;;:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;225680:37:0;;;;;;;;;;;;:::i;227442:144::-;227485:4;;;;227484:5;227476:36;;;;-1:-1:-1;;;227476:36:0;;4452:2:1;227476:36:0;;;4434:21:1;4491:2;4471:18;;;4464:30;-1:-1:-1;;;4510:18:1;;;4503:48;4568:18;;227476:36:0;;;;;;;;;227523:4;:11;;-1:-1:-1;;227523:11:0;227530:4;227523:11;;;;;;:4;227574:3;227545:33;;-1:-1:-1;;;227545:33:0;;-1:-1:-1;;;;;227545:5:0;:10;;;;:33;;227556:6;;227564:3;;227530:4;;227545:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;227545:33:0;;;;;;;;;;;;:::i;:::-;;227442:144::o;226706:728::-;226771:10;226752:15;:29;;226744:67;;;;-1:-1:-1;;;226744:67:0;;6843:2:1;226744:67:0;;;6825:21:1;6882:2;6862:18;;;6855:30;-1:-1:-1;;;6901:18:1;;;6894:55;6966:18;;226744:67:0;6641:349:1;226744:67:0;226830:3;;:8;226822:58;;;;-1:-1:-1;;;226822:58:0;;7197:2:1;226822:58:0;;;7179:21:1;7236:2;7216:18;;;7209:30;7275:34;7255:18;;;7248:62;-1:-1:-1;;;7326:18:1;;;7319:35;7371:19;;226822:58:0;6995:401:1;226822:58:0;227325:57;227358:5;-1:-1:-1;;;;;227348:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;227330:42;;:15;:42;:::i;:::-;225271:10;227325:4;:57::i;:::-;227319:3;:63;;;227393:33;;-1:-1:-1;;;227393:33:0;;-1:-1:-1;;;;;227393:5:0;:10;;;;:33;;227404:6;;227412:3;;227417;;227393:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;226706:728::o;225856:132::-;225903:16;225976:3;;225939:41;;-1:-1:-1;;;225939:41:0;;;;;1274:25:1;;;;225955:6:0;-1:-1:-1;;;;;225939:36:0;;;;1247:18:1;;225939:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;227594:107::-;227653:7;227684:1;227680;:5;:13;;227692:1;227680:13;;;227688:1;227680:13;227673:20;;227594:107;;;;;:::o;168:250:1:-;253:1;263:113;277:6;274:1;271:13;263:113;;;353:11;;;347:18;334:11;;;327:39;299:2;292:10;263:113;;;-1:-1:-1;;410:1:1;392:16;;385:27;168:250::o;423:270::-;464:3;502:5;496:12;529:6;524:3;517:19;545:76;614:6;607:4;602:3;598:14;591:4;584:5;580:16;545:76;:::i;:::-;675:2;654:15;-1:-1:-1;;650:29:1;641:39;;;;682:4;637:50;;423:270;-1:-1:-1;;423:270:1:o;698:217::-;845:2;834:9;827:21;808:4;865:44;905:2;894:9;890:18;882:6;865:44;:::i;2367:380::-;2446:1;2442:12;;;;2489;;;2510:61;;2564:4;2556:6;2552:17;2542:27;;2510:61;2617:2;2609:6;2606:14;2586:18;2583:38;2580:161;;2663:10;2658:3;2654:20;2651:1;2644:31;2698:4;2695:1;2688:15;2726:4;2723:1;2716:15;2580:161;;2367:380;;;:::o;2752:277::-;2819:6;2872:2;2860:9;2851:7;2847:23;2843:32;2840:52;;;2888:1;2885;2878:12;2840:52;2920:9;2914:16;2973:5;2966:13;2959:21;2952:5;2949:32;2939:60;;2995:1;2992;2985:12;2939:60;3018:5;2752:277;-1:-1:-1;;;2752:277:1:o;3034:127::-;3095:10;3090:3;3086:20;3083:1;3076:31;3126:4;3123:1;3116:15;3150:4;3147:1;3140:15;3166:615;3242:5;-1:-1:-1;;;;;3302:14:1;;;3299:40;;;3319:18;;:::i;:::-;3394:2;3388:9;3362:2;3448:15;;-1:-1:-1;;3444:24:1;;;3470:2;3440:33;3436:42;3424:55;;;3494:18;;;3514:22;;;3491:46;3488:72;;;3540:18;;:::i;:::-;3580:10;3576:2;3569:22;3609:6;3600:15;;3639:6;3631;3624:22;3679:3;3670:6;3665:3;3661:16;3658:25;3655:45;;;3696:1;3693;3686:12;3655:45;3709:66;3768:6;3761:4;3753:6;3749:17;3744:3;3709:66;:::i;:::-;;;;3166:615;;;;;:::o;3786:459::-;3866:6;3919:2;3907:9;3898:7;3894:23;3890:32;3887:52;;;3935:1;3932;3925:12;3887:52;3962:16;;-1:-1:-1;;;;;3990:30:1;;3987:50;;;4033:1;4030;4023:12;3987:50;4056:22;;4109:4;4101:13;;4097:27;-1:-1:-1;4087:55:1;;4138:1;4135;4128:12;4087:55;4161:78;4231:7;4226:2;4220:9;4215:2;4211;4207:11;4161:78;:::i;:::-;4151:88;3786:459;-1:-1:-1;;;;3786:459:1:o;4722:1451::-;-1:-1:-1;;;;;4950:32:1;;4932:51;;5002:2;5020:18;;;5013:34;;;5083:3;5078:2;5063:18;;5056:31;5134:13;;4913:4;;5002:2;4913:4;;4979:1;5212:18;;;;5265;;;;5292:61;;5346:4;5338:6;5334:17;5324:27;;5292:61;5399:2;5391:6;5388:14;5368:18;5365:38;5362:165;;-1:-1:-1;;;5426:33:1;;5482:4;5479:1;5472:15;5512:4;5433:3;5500:17;5362:165;5597:3;5582:19;;100;;;143:14;;;5626:18;5653:128;;;;5795:1;5790:314;;;;5619:485;;5653:128;-1:-1:-1;;5686:24:1;;5674:37;;5754:14;;5747:22;5744:1;5740:30;5731:40;;;-1:-1:-1;5653:128:1;;5790:314;4669:1;4662:14;;;4706:4;4693:18;;5884:1;5898:165;5912:6;5909:1;5906:13;5898:165;;;5990:14;;5977:11;;;5970:35;6033:16;;;;5927:10;;5898:165;;;6083:11;;;-1:-1:-1;;5619:485:1;;;;;;;6121:3;6113:11;;;;6160:6;6155:2;6144:9;6140:18;6133:34;4722:1451;;;;;;;:::o;7401:184::-;7471:6;7524:2;7512:9;7503:7;7499:23;7495:32;7492:52;;;7540:1;7537;7530:12;7492:52;-1:-1:-1;7563:16:1;;7401:184;-1:-1:-1;7401:184:1:o;7590:222::-;7655:9;;;7676:10;;;7673:133;;;7728:10;7723:3;7719:20;7716:1;7709:31;7763:4;7760:1;7753:15;7791:4;7788:1;7781:15

Swarm Source

ipfs://05c844bebe2f4b902a2272c81caf4bbaa4e573e5589fbc2f8aaa8d20f258a275

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.