ETH Price: $2,974.35 (-4.47%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Cast225174712025-05-19 14:01:47246 days ago1747663307IN
0x53222d00...98793bB07
0 ETH0.009512383.45021968
Schedule224964102025-05-16 15:05:59249 days ago1747407959IN
0x53222d00...98793bB07
0 ETH0.000078713.34549856
Schedule224963892025-05-16 15:01:35249 days ago1747407695IN
0x53222d00...98793bB07
0 ETH0.000290813.14207031

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x60a06040224897982025-05-15 16:47:35250 days ago1747327655
0x53222d00...98793bB07
 Contract Creation0 ETH
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
DssSpell

Compiler Version
v0.8.16+commit.07a7930e

Optimization Enabled:
Yes with 200 runs

Other Settings:
london EvmVersion, GNU AGPLv3 license
/**
 *Submitted for verification at Etherscan.io on 2025-05-15
*/

// 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.16;
pragma experimental ABIEncoderV2;

// 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-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/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/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/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-exec-lib/src/DssExec.sol

//
// DssExec.sol -- MakerDAO Executive Spell Template
//
// 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 PauseAbstract {
    function delay() external view returns (uint256);
    function plot(address, bytes32, bytes calldata, uint256) external;
    function exec(address, bytes32, bytes calldata, uint256) external returns (bytes memory);
}

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

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

contract DssExec {

    Changelog      constant public log   = Changelog(0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F);
    uint256                 public eta;
    bytes                   public sig;
    bool                    public done;
    bytes32       immutable public tag;
    address       immutable public action;
    uint256       immutable public expiration;
    PauseAbstract immutable public pause;

    // 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 SpellAction(action).description();
    }

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

    function nextCastTime() external view returns (uint256 castTime) {
        return SpellAction(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       = PauseAbstract(log.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");
        eta = block.timestamp + PauseAbstract(pause).delay();
        pause.plot(action, tag, sig, eta);
    }

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

// 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/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/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/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/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);
}

// src/dependencies/lockstake/LockstakeInstance.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 LockstakeInstance {
    address lssky;
    address engine;
    address clipper;
    address clipperCalc;
    address migrator;
}

// 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/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/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/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);
}

// src/dependencies/endgame-toolkit/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;
}

// 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/forge-std/src/Vm.sol
// Automatically @generated by scripts/vm.py. Do not modify manually.

/// 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 {
    /// A modification applied to either `msg.sender` or `tx.origin`. Returned by `readCallers`.
    enum CallerMode {
        // No caller modification is currently active.
        None,
        // A one time broadcast triggered by a `vm.broadcast()` call is currently active.
        Broadcast,
        // A recurrent broadcast triggered by a `vm.startBroadcast()` call is currently active.
        RecurrentBroadcast,
        // A one time prank triggered by a `vm.prank()` call is currently active.
        Prank,
        // A recurrent prank triggered by a `vm.startPrank()` call is currently active.
        RecurrentPrank
    }

    /// The kind of account access that occurred.
    enum AccountAccessKind {
        // The account was called.
        Call,
        // The account was called via delegatecall.
        DelegateCall,
        // The account was called via callcode.
        CallCode,
        // The account was called via staticcall.
        StaticCall,
        // The account was created.
        Create,
        // The account was selfdestructed.
        SelfDestruct,
        // Synthetic access indicating the current context has resumed after a previous sub-context (AccountAccess).
        Resume,
        // The account's balance was read.
        Balance,
        // The account's codesize was read.
        Extcodesize,
        // The account's codehash was read.
        Extcodehash,
        // The account's code was copied.
        Extcodecopy
    }

    /// Forge execution contexts.
    enum ForgeContext {
        // Test group execution context (test, coverage or snapshot).
        TestGroup,
        // `forge test` execution context.
        Test,
        // `forge coverage` execution context.
        Coverage,
        // `forge snapshot` execution context.
        Snapshot,
        // Script group execution context (dry run, broadcast or resume).
        ScriptGroup,
        // `forge script` execution context.
        ScriptDryRun,
        // `forge script --broadcast` execution context.
        ScriptBroadcast,
        // `forge script --resume` execution context.
        ScriptResume,
        // Unknown `forge` execution context.
        Unknown
    }

    /// An Ethereum log. Returned by `getRecordedLogs`.
    struct Log {
        // The topics of the log, including the signature, if any.
        bytes32[] topics;
        // The raw data of the log.
        bytes data;
        // The address of the log's emitter.
        address emitter;
    }

    /// An RPC URL and its alias. Returned by `rpcUrlStructs`.
    struct Rpc {
        // The alias of the RPC URL.
        string key;
        // The RPC URL.
        string url;
    }

    /// An RPC log object. Returned by `eth_getLogs`.
    struct EthGetLogs {
        // The address of the log's emitter.
        address emitter;
        // The topics of the log, including the signature, if any.
        bytes32[] topics;
        // The raw data of the log.
        bytes data;
        // The block hash.
        bytes32 blockHash;
        // The block number.
        uint64 blockNumber;
        // The transaction hash.
        bytes32 transactionHash;
        // The transaction index in the block.
        uint64 transactionIndex;
        // The log index.
        uint256 logIndex;
        // Whether the log was removed.
        bool removed;
    }

    /// A single entry in a directory listing. Returned by `readDir`.
    struct DirEntry {
        // The error message, if any.
        string errorMessage;
        // The path of the entry.
        string path;
        // The depth of the entry.
        uint64 depth;
        // Whether the entry is a directory.
        bool isDir;
        // Whether the entry is a symlink.
        bool isSymlink;
    }

    /// Metadata information about a file.
    /// This structure is returned from the `fsMetadata` function and represents known
    /// metadata about a file such as its permissions, size, modification
    /// times, etc.
    struct FsMetadata {
        // True if this metadata is for a directory.
        bool isDir;
        // True if this metadata is for a symlink.
        bool isSymlink;
        // The size of the file, in bytes, this metadata is for.
        uint256 length;
        // True if this metadata is for a readonly (unwritable) file.
        bool readOnly;
        // The last modification time listed in this metadata.
        uint256 modified;
        // The last access time of this metadata.
        uint256 accessed;
        // The creation time listed in this metadata.
        uint256 created;
    }

    /// A wallet with a public and private key.
    struct Wallet {
        // The wallet's address.
        address addr;
        // The wallet's public key `X`.
        uint256 publicKeyX;
        // The wallet's public key `Y`.
        uint256 publicKeyY;
        // The wallet's private key.
        uint256 privateKey;
    }

    /// The result of a `tryFfi` call.
    struct FfiResult {
        // The exit code of the call.
        int32 exitCode;
        // The optionally hex-decoded `stdout` data.
        bytes stdout;
        // The `stderr` data.
        bytes stderr;
    }

    /// Information on the chain and fork.
    struct ChainInfo {
        // The fork identifier. Set to zero if no fork is active.
        uint256 forkId;
        // The chain ID of the current fork.
        uint256 chainId;
    }

    /// The result of a `stopAndReturnStateDiff` call.
    struct AccountAccess {
        // The chain and fork the access occurred.
        ChainInfo chainInfo;
        // The kind of account access that determines what the account is.
        // If kind is Call, DelegateCall, StaticCall or CallCode, then the account is the callee.
        // If kind is Create, then the account is the newly created account.
        // If kind is SelfDestruct, then the account is the selfdestruct recipient.
        // If kind is a Resume, then account represents a account context that has resumed.
        AccountAccessKind kind;
        // The account that was accessed.
        // It's either the account created, callee or a selfdestruct recipient for CREATE, CALL or SELFDESTRUCT.
        address account;
        // What accessed the account.
        address accessor;
        // If the account was initialized or empty prior to the access.
        // An account is considered initialized if it has code, a
        // non-zero nonce, or a non-zero balance.
        bool initialized;
        // The previous balance of the accessed account.
        uint256 oldBalance;
        // The potential new balance of the accessed account.
        // That is, all balance changes are recorded here, even if reverts occurred.
        uint256 newBalance;
        // Code of the account deployed by CREATE.
        bytes deployedCode;
        // Value passed along with the account access
        uint256 value;
        // Input data provided to the CREATE or CALL
        bytes data;
        // If this access reverted in either the current or parent context.
        bool reverted;
        // An ordered list of storage accesses made during an account access operation.
        StorageAccess[] storageAccesses;
        // Call depth traversed during the recording of state differences
        uint64 depth;
    }

    /// The storage accessed during an `AccountAccess`.
    struct StorageAccess {
        // The account whose storage was accessed.
        address account;
        // The slot that was accessed.
        bytes32 slot;
        // If the access was a write.
        bool isWrite;
        // The previous value of the slot.
        bytes32 previousValue;
        // The new value of the slot.
        bytes32 newValue;
        // If the access was reverted.
        bool reverted;
    }

    /// Gas used. Returned by `lastCallGas`.
    struct Gas {
        // The gas limit of the call.
        uint64 gasLimit;
        // The total gas used.
        uint64 gasTotalUsed;
        // The amount of gas used for memory expansion.
        uint64 gasMemoryUsed;
        // The amount of gas refunded.
        int64 gasRefunded;
        // The amount of gas remaining.
        uint64 gasRemaining;
    }

    // ======== Environment ========

    /// Gets the environment variable `name` and parses it as `address`.
    /// Reverts if the variable was not found or could not be parsed.
    function envAddress(string calldata name) external view returns (address value);

    /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`.
    /// Reverts if the variable was not found or could not be parsed.
    function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value);

    /// Gets the environment variable `name` and parses it as `bool`.
    /// Reverts if the variable was not found or could not be parsed.
    function envBool(string calldata name) external view returns (bool value);

    /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`.
    /// Reverts if the variable was not found or could not be parsed.
    function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value);

    /// Gets the environment variable `name` and parses it as `bytes32`.
    /// Reverts if the variable was not found or could not be parsed.
    function envBytes32(string calldata name) external view returns (bytes32 value);

    /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`.
    /// Reverts if the variable was not found or could not be parsed.
    function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value);

    /// Gets the environment variable `name` and parses it as `bytes`.
    /// Reverts if the variable was not found or could not be parsed.
    function envBytes(string calldata name) external view returns (bytes memory value);

    /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`.
    /// Reverts if the variable was not found or could not be parsed.
    function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value);

    /// Gets the environment variable `name` and returns true if it exists, else returns false.
    function envExists(string calldata name) external view returns (bool result);

    /// Gets the environment variable `name` and parses it as `int256`.
    /// Reverts if the variable was not found or could not be parsed.
    function envInt(string calldata name) external view returns (int256 value);

    /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`.
    /// Reverts if the variable was not found or could not be parsed.
    function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value);

    /// Gets the environment variable `name` and parses it as `bool`.
    /// Reverts if the variable could not be parsed.
    /// Returns `defaultValue` if the variable was not found.
    function envOr(string calldata name, bool defaultValue) external view returns (bool value);

    /// Gets the environment variable `name` and parses it as `uint256`.
    /// Reverts if the variable could not be parsed.
    /// Returns `defaultValue` if the variable was not found.
    function envOr(string calldata name, uint256 defaultValue) external view returns (uint256 value);

    /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`.
    /// Reverts if the variable could not be parsed.
    /// Returns `defaultValue` if the variable was not found.
    function envOr(string calldata name, string calldata delim, address[] calldata defaultValue)
        external
        view
        returns (address[] memory value);

    /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`.
    /// Reverts if the variable could not be parsed.
    /// Returns `defaultValue` if the variable was not found.
    function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue)
        external
        view
        returns (bytes32[] memory value);

    /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`.
    /// Reverts if the variable could not be parsed.
    /// Returns `defaultValue` if the variable was not found.
    function envOr(string calldata name, string calldata delim, string[] calldata defaultValue)
        external
        view
        returns (string[] memory value);

    /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`.
    /// Reverts if the variable could not be parsed.
    /// Returns `defaultValue` if the variable was not found.
    function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue)
        external
        view
        returns (bytes[] memory value);

    /// Gets the environment variable `name` and parses it as `int256`.
    /// Reverts if the variable could not be parsed.
    /// Returns `defaultValue` if the variable was not found.
    function envOr(string calldata name, int256 defaultValue) external view returns (int256 value);

    /// Gets the environment variable `name` and parses it as `address`.
    /// Reverts if the variable could not be parsed.
    /// Returns `defaultValue` if the variable was not found.
    function envOr(string calldata name, address defaultValue) external view returns (address value);

    /// Gets the environment variable `name` and parses it as `bytes32`.
    /// Reverts if the variable could not be parsed.
    /// Returns `defaultValue` if the variable was not found.
    function envOr(string calldata name, bytes32 defaultValue) external view returns (bytes32 value);

    /// Gets the environment variable `name` and parses it as `string`.
    /// Reverts if the variable could not be parsed.
    /// Returns `defaultValue` if the variable was not found.
    function envOr(string calldata name, string calldata defaultValue) external view returns (string memory value);

    /// Gets the environment variable `name` and parses it as `bytes`.
    /// Reverts if the variable could not be parsed.
    /// Returns `defaultValue` if the variable was not found.
    function envOr(string calldata name, bytes calldata defaultValue) external view returns (bytes memory value);

    /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`.
    /// Reverts if the variable could not be parsed.
    /// Returns `defaultValue` if the variable was not found.
    function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue)
        external
        view
        returns (bool[] memory value);

    /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`.
    /// Reverts if the variable could not be parsed.
    /// Returns `defaultValue` if the variable was not found.
    function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue)
        external
        view
        returns (uint256[] memory value);

    /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`.
    /// Reverts if the variable could not be parsed.
    /// Returns `defaultValue` if the variable was not found.
    function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue)
        external
        view
        returns (int256[] memory value);

    /// Gets the environment variable `name` and parses it as `string`.
    /// Reverts if the variable was not found or could not be parsed.
    function envString(string calldata name) external view returns (string memory value);

    /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`.
    /// Reverts if the variable was not found or could not be parsed.
    function envString(string calldata name, string calldata delim) external view returns (string[] memory value);

    /// Gets the environment variable `name` and parses it as `uint256`.
    /// Reverts if the variable was not found or could not be parsed.
    function envUint(string calldata name) external view returns (uint256 value);

    /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`.
    /// Reverts if the variable was not found or could not be parsed.
    function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value);

    /// Returns true if `forge` command was executed in given context.
    function isContext(ForgeContext context) external view returns (bool result);

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

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

    /// 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);

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

    /// 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);

    /// Gets the current `block.blobbasefee`.
    /// You should use this instead of `block.blobbasefee` if you use `vm.blobBaseFee`, as `block.blobbasefee` is assumed to be constant across a transaction,
    /// and as a result will get optimized out by the compiler.
    /// See https://github.com/foundry-rs/foundry/issues/6180
    function getBlobBaseFee() external view returns (uint256 blobBaseFee);

    /// Gets the current `block.number`.
    /// You should use this instead of `block.number` if you use `vm.roll`, as `block.number` is assumed to be constant across a transaction,
    /// and as a result will get optimized out by the compiler.
    /// See https://github.com/foundry-rs/foundry/issues/6180
    function getBlockNumber() external view returns (uint256 height);

    /// Gets the current `block.timestamp`.
    /// You should use this instead of `block.timestamp` if you use `vm.warp`, as `block.timestamp` is assumed to be constant across a transaction,
    /// and as a result will get optimized out by the compiler.
    /// See https://github.com/foundry-rs/foundry/issues/6180
    function getBlockTimestamp() external view returns (uint256 timestamp);

    /// 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);

    /// 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 nonce of an account.
    function getNonce(address account) external view returns (uint64 nonce);

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

    /// Gets the gas used in the last call.
    function lastCallGas() external view returns (Gas memory gas);

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

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

    /// Records all storage reads and writes.
    function record() external;

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

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

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

    /// Signs `digest` with `privateKey` using the secp256r1 curve.
    function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s);

    /// Signs `digest` with `privateKey` using the secp256k1 curve.
    function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);

    /// Signs `digest` with signer provided to script using the secp256k1 curve.
    /// If `--sender` is provided, the signer with provided address is used, otherwise,
    /// if exactly one signer is provided to the script, that signer is used.
    /// Raises error if signer passed through `--sender` does not match any unlocked signers or
    /// if `--sender` is not provided and not exactly one signer is passed to the script.
    function sign(bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);

    /// Signs `digest` with signer provided to script using the secp256k1 curve.
    /// Raises error if none of the signers passed into the script have provided address.
    function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);

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

    /// 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);

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

    // ======== Filesystem ========

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

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

    /// Performs a foreign function call via the terminal.
    function ffi(string[] calldata commandInput) external returns (bytes memory 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);

    /// Gets the creation bytecode from an artifact file. Takes in the relative path to the json file or the path to the
    /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
    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 or the path to the
    /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
    function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode);

    /// 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);

    /// Prompts the user for a string value in the terminal.
    function prompt(string calldata promptText) external returns (string memory input);

    /// Prompts the user for an address in the terminal.
    function promptAddress(string calldata promptText) external returns (address);

    /// Prompts the user for a hidden string value in the terminal.
    function promptSecret(string calldata promptText) external returns (string memory input);

    /// Prompts the user for uint256 in the terminal.
    function promptUint(string calldata promptText) external returns (uint256);

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

    /// See `readDir(string)`.
    function readDir(string calldata path, uint64 maxDepth) external view returns (DirEntry[] memory entries);

    /// See `readDir(string)`.
    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;

    /// 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);

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

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

    // ======== JSON ========

    /// Checks if `key` exists in a JSON object
    /// `keyExists` is being deprecated in favor of `keyExistsJson`. It will be removed in future versions.
    function keyExists(string calldata json, string calldata key) external view returns (bool);

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

    /// Parses a string of JSON data at `key` and coerces it to `address`.
    function parseJsonAddress(string calldata json, string calldata key) external pure returns (address);

    /// Parses a string of JSON data at `key` and coerces it to `address[]`.
    function parseJsonAddressArray(string calldata json, string calldata key)
        external
        pure
        returns (address[] memory);

    /// Parses a string of JSON data at `key` and coerces it to `bool`.
    function parseJsonBool(string calldata json, string calldata key) external pure returns (bool);

    /// Parses a string of JSON data at `key` and coerces it to `bool[]`.
    function parseJsonBoolArray(string calldata json, string calldata key) external pure returns (bool[] memory);

    /// Parses a string of JSON data at `key` and coerces it to `bytes`.
    function parseJsonBytes(string calldata json, string calldata key) external pure returns (bytes memory);

    /// Parses a string of JSON data at `key` and coerces it to `bytes32`.
    function parseJsonBytes32(string calldata json, string calldata key) external pure returns (bytes32);

    /// Parses a string of JSON data at `key` and coerces it to `bytes32[]`.
    function parseJsonBytes32Array(string calldata json, string calldata key)
        external
        pure
        returns (bytes32[] memory);

    /// Parses a string of JSON data at `key` and coerces it to `bytes[]`.
    function parseJsonBytesArray(string calldata json, string calldata key) external pure returns (bytes[] memory);

    /// Parses a string of JSON data at `key` and coerces it to `int256`.
    function parseJsonInt(string calldata json, string calldata key) external pure returns (int256);

    /// Parses a string of JSON data at `key` and coerces it to `int256[]`.
    function parseJsonIntArray(string calldata json, string calldata key) external pure returns (int256[] memory);

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

    /// Parses a string of JSON data at `key` and coerces it to `string`.
    function parseJsonString(string calldata json, string calldata key) external pure returns (string memory);

    /// Parses a string of JSON data at `key` and coerces it to `string[]`.
    function parseJsonStringArray(string calldata json, string calldata key) external pure returns (string[] memory);

    /// Parses a string of JSON data at `key` and coerces it to `uint256`.
    function parseJsonUint(string calldata json, string calldata key) external pure returns (uint256);

    /// Parses a string of JSON data at `key` and coerces it to `uint256[]`.
    function parseJsonUintArray(string calldata json, string calldata key) external pure returns (uint256[] memory);

    /// ABI-encodes a JSON object.
    function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData);

    /// ABI-encodes a JSON object at `key`.
    function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData);

    /// See `serializeJson`.
    function serializeAddress(string calldata objectKey, string calldata valueKey, address value)
        external
        returns (string memory json);

    /// See `serializeJson`.
    function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values)
        external
        returns (string memory json);

    /// See `serializeJson`.
    function serializeBool(string calldata objectKey, string calldata valueKey, bool value)
        external
        returns (string memory json);

    /// See `serializeJson`.
    function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values)
        external
        returns (string memory json);

    /// See `serializeJson`.
    function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value)
        external
        returns (string memory json);

    /// See `serializeJson`.
    function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values)
        external
        returns (string memory json);

    /// See `serializeJson`.
    function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value)
        external
        returns (string memory json);

    /// See `serializeJson`.
    function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values)
        external
        returns (string memory json);

    /// See `serializeJson`.
    function serializeInt(string calldata objectKey, string calldata valueKey, int256 value)
        external
        returns (string memory json);

    /// See `serializeJson`.
    function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values)
        external
        returns (string memory json);

    /// Serializes a key and value to a JSON object stored in-memory that can be later written to a file.
    /// 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);

    /// See `serializeJson`.
    function serializeString(string calldata objectKey, string calldata valueKey, string calldata value)
        external
        returns (string memory json);

    /// See `serializeJson`.
    function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values)
        external
        returns (string memory json);

    /// See `serializeJson`.
    function serializeUintToHex(string calldata objectKey, string calldata valueKey, uint256 value)
        external
        returns (string memory json);

    /// See `serializeJson`.
    function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value)
        external
        returns (string memory json);

    /// See `serializeJson`.
    function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values)
        external
        returns (string memory json);

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

    // ======== Scripting ========

    /// Has the next call (at this call depth only) create transactions that can later be signed and sent onchain.
    /// Broadcasting address is determined by checking the following in order:
    /// 1. If `--sender` argument was provided, that address is used.
    /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used.
    /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used.
    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;

    /// Has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain.
    /// Broadcasting address is determined by checking the following in order:
    /// 1. If `--sender` argument was provided, that address is used.
    /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used.
    /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used.
    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;

    // ======== String ========

    /// Returns the index of the first occurrence of a `key` in an `input` string.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `key` is not found.
    /// Returns 0 in case of an empty `key`.
    function indexOf(string calldata input, string calldata key) external pure returns (uint256);

    /// Parses the given `string` into an `address`.
    function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue);

    /// Parses the given `string` into a `bool`.
    function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue);

    /// Parses the given `string` into `bytes`.
    function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue);

    /// Parses the given `string` into a `bytes32`.
    function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue);

    /// Parses the given `string` into a `int256`.
    function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue);

    /// Parses the given `string` into a `uint256`.
    function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue);

    /// Replaces occurrences of `from` in the given `string` with `to`.
    function replace(string calldata input, string calldata from, string calldata to)
        external
        pure
        returns (string memory output);

    /// Splits the given `string` into an array of strings divided by the `delimiter`.
    function split(string calldata input, string calldata delimiter) external pure returns (string[] memory outputs);

    /// Converts the given `string` value to Lowercase.
    function toLowercase(string calldata input) external pure returns (string memory output);

    /// Converts the given value to a `string`.
    function toString(address value) external pure returns (string memory stringifiedValue);

    /// Converts the given value to a `string`.
    function toString(bytes calldata value) external pure returns (string memory stringifiedValue);

    /// Converts the given value to a `string`.
    function toString(bytes32 value) external pure returns (string memory stringifiedValue);

    /// Converts the given value to a `string`.
    function toString(bool value) external pure returns (string memory stringifiedValue);

    /// Converts the given value to a `string`.
    function toString(uint256 value) external pure returns (string memory stringifiedValue);

    /// Converts the given value to a `string`.
    function toString(int256 value) external pure returns (string memory stringifiedValue);

    /// Converts the given `string` value to Uppercase.
    function toUppercase(string calldata input) external pure returns (string memory output);

    /// Trims leading and trailing whitespace from the given `string` value.
    function trim(string calldata input) external pure returns (string memory output);

    // ======== Testing ========

    /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
    /// Formats values with decimals in failure message.
    function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) external pure;

    /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
    function assertApproxEqAbsDecimal(
        uint256 left,
        uint256 right,
        uint256 maxDelta,
        uint256 decimals,
        string calldata error
    ) external pure;

    /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
    /// Formats values with decimals in failure message.
    function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) external pure;

    /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
    function assertApproxEqAbsDecimal(
        int256 left,
        int256 right,
        uint256 maxDelta,
        uint256 decimals,
        string calldata error
    ) external pure;

    /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
    function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) external pure;

    /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
    /// Includes error message into revert string on failure.
    function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata error) external pure;

    /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
    function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) external pure;

    /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
    /// Includes error message into revert string on failure.
    function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata error) external pure;

    /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
    /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
    /// Formats values with decimals in failure message.
    function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals)
        external
        pure;

    /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
    /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
    function assertApproxEqRelDecimal(
        uint256 left,
        uint256 right,
        uint256 maxPercentDelta,
        uint256 decimals,
        string calldata error
    ) external pure;

    /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
    /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
    /// Formats values with decimals in failure message.
    function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals)
        external
        pure;

    /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
    /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
    function assertApproxEqRelDecimal(
        int256 left,
        int256 right,
        uint256 maxPercentDelta,
        uint256 decimals,
        string calldata error
    ) external pure;

    /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
    /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
    function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta) external pure;

    /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
    /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
    /// Includes error message into revert string on failure.
    function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata error)
        external
        pure;

    /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
    /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
    function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) external pure;

    /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
    /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
    /// Includes error message into revert string on failure.
    function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata error)
        external
        pure;

    /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message.
    function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure;

    /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message.
    /// Includes error message into revert string on failure.
    function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;

    /// Asserts that two `int256` values are equal, formatting them with decimals in failure message.
    function assertEqDecimal(int256 left, int256 right, uint256 decimals) external pure;

    /// Asserts that two `int256` values are equal, formatting them with decimals in failure message.
    /// Includes error message into revert string on failure.
    function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;

    /// Asserts that two `bool` values are equal.
    function assertEq(bool left, bool right) external pure;

    /// Asserts that two `bool` values are equal and includes error message into revert string on failure.
    function assertEq(bool left, bool right, string calldata error) external pure;

    /// Asserts that two `string` values are equal.
    function assertEq(string calldata left, string calldata right) external pure;

    /// Asserts that two `string` values are equal and includes error message into revert string on failure.
    function assertEq(string calldata left, string calldata right, string calldata error) external pure;

    /// Asserts that two `bytes` values are equal.
    function assertEq(bytes calldata left, bytes calldata right) external pure;

    /// Asserts that two `bytes` values are equal and includes error message into revert string on failure.
    function assertEq(bytes calldata left, bytes calldata right, string calldata error) external pure;

    /// Asserts that two arrays of `bool` values are equal.
    function assertEq(bool[] calldata left, bool[] calldata right) external pure;

    /// Asserts that two arrays of `bool` values are equal and includes error message into revert string on failure.
    function assertEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure;

    /// Asserts that two arrays of `uint256 values are equal.
    function assertEq(uint256[] calldata left, uint256[] calldata right) external pure;

    /// Asserts that two arrays of `uint256` values are equal and includes error message into revert string on failure.
    function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure;

    /// Asserts that two arrays of `int256` values are equal.
    function assertEq(int256[] calldata left, int256[] calldata right) external pure;

    /// Asserts that two arrays of `int256` values are equal and includes error message into revert string on failure.
    function assertEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure;

    /// Asserts that two `uint256` values are equal.
    function assertEq(uint256 left, uint256 right) external pure;

    /// Asserts that two arrays of `address` values are equal.
    function assertEq(address[] calldata left, address[] calldata right) external pure;

    /// Asserts that two arrays of `address` values are equal and includes error message into revert string on failure.
    function assertEq(address[] calldata left, address[] calldata right, string calldata error) external pure;

    /// Asserts that two arrays of `bytes32` values are equal.
    function assertEq(bytes32[] calldata left, bytes32[] calldata right) external pure;

    /// Asserts that two arrays of `bytes32` values are equal and includes error message into revert string on failure.
    function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure;

    /// Asserts that two arrays of `string` values are equal.
    function assertEq(string[] calldata left, string[] calldata right) external pure;

    /// Asserts that two arrays of `string` values are equal and includes error message into revert string on failure.
    function assertEq(string[] calldata left, string[] calldata right, string calldata error) external pure;

    /// Asserts that two arrays of `bytes` values are equal.
    function assertEq(bytes[] calldata left, bytes[] calldata right) external pure;

    /// Asserts that two arrays of `bytes` values are equal and includes error message into revert string on failure.
    function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure;

    /// Asserts that two `uint256` values are equal and includes error message into revert string on failure.
    function assertEq(uint256 left, uint256 right, string calldata error) external pure;

    /// Asserts that two `int256` values are equal.
    function assertEq(int256 left, int256 right) external pure;

    /// Asserts that two `int256` values are equal and includes error message into revert string on failure.
    function assertEq(int256 left, int256 right, string calldata error) external pure;

    /// Asserts that two `address` values are equal.
    function assertEq(address left, address right) external pure;

    /// Asserts that two `address` values are equal and includes error message into revert string on failure.
    function assertEq(address left, address right, string calldata error) external pure;

    /// Asserts that two `bytes32` values are equal.
    function assertEq(bytes32 left, bytes32 right) external pure;

    /// Asserts that two `bytes32` values are equal and includes error message into revert string on failure.
    function assertEq(bytes32 left, bytes32 right, string calldata error) external pure;

    /// Asserts that the given condition is false.
    function assertFalse(bool condition) external pure;

    /// Asserts that the given condition is false and includes error message into revert string on failure.
    function assertFalse(bool condition, string calldata error) external pure;

    /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
    /// Formats values with decimals in failure message.
    function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) external pure;

    /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
    function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;

    /// Compares two `int256` values. Expects first value to be greater than or equal to second.
    /// Formats values with decimals in failure message.
    function assertGeDecimal(int256 left, int256 right, uint256 decimals) external pure;

    /// Compares two `int256` values. Expects first value to be greater than or equal to second.
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
    function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;

    /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
    function assertGe(uint256 left, uint256 right) external pure;

    /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
    /// Includes error message into revert string on failure.
    function assertGe(uint256 left, uint256 right, string calldata error) external pure;

    /// Compares two `int256` values. Expects first value to be greater than or equal to second.
    function assertGe(int256 left, int256 right) external pure;

    /// Compares two `int256` values. Expects first value to be greater than or equal to second.
    /// Includes error message into revert string on failure.
    function assertGe(int256 left, int256 right, string calldata error) external pure;

    /// Compares two `uint256` values. Expects first value to be greater than second.
    /// Formats values with decimals in failure message.
    function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) external pure;

    /// Compares two `uint256` values. Expects first value to be greater than second.
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
    function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;

    /// Compares two `int256` values. Expects first value to be greater than second.
    /// Formats values with decimals in failure message.
    function assertGtDecimal(int256 left, int256 right, uint256 decimals) external pure;

    /// Compares two `int256` values. Expects first value to be greater than second.
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
    function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;

    /// Compares two `uint256` values. Expects first value to be greater than second.
    function assertGt(uint256 left, uint256 right) external pure;

    /// Compares two `uint256` values. Expects first value to be greater than second.
    /// Includes error message into revert string on failure.
    function assertGt(uint256 left, uint256 right, string calldata error) external pure;

    /// Compares two `int256` values. Expects first value to be greater than second.
    function assertGt(int256 left, int256 right) external pure;

    /// Compares two `int256` values. Expects first value to be greater than second.
    /// Includes error message into revert string on failure.
    function assertGt(int256 left, int256 right, string calldata error) external pure;

    /// Compares two `uint256` values. Expects first value to be less than or equal to second.
    /// Formats values with decimals in failure message.
    function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) external pure;

    /// Compares two `uint256` values. Expects first value to be less than or equal to second.
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
    function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;

    /// Compares two `int256` values. Expects first value to be less than or equal to second.
    /// Formats values with decimals in failure message.
    function assertLeDecimal(int256 left, int256 right, uint256 decimals) external pure;

    /// Compares two `int256` values. Expects first value to be less than or equal to second.
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
    function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;

    /// Compares two `uint256` values. Expects first value to be less than or equal to second.
    function assertLe(uint256 left, uint256 right) external pure;

    /// Compares two `uint256` values. Expects first value to be less than or equal to second.
    /// Includes error message into revert string on failure.
    function assertLe(uint256 left, uint256 right, string calldata error) external pure;

    /// Compares two `int256` values. Expects first value to be less than or equal to second.
    function assertLe(int256 left, int256 right) external pure;

    /// Compares two `int256` values. Expects first value to be less than or equal to second.
    /// Includes error message into revert string on failure.
    function assertLe(int256 left, int256 right, string calldata error) external pure;

    /// Compares two `uint256` values. Expects first value to be less than second.
    /// Formats values with decimals in failure message.
    function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) external pure;

    /// Compares two `uint256` values. Expects first value to be less than second.
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
    function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;

    /// Compares two `int256` values. Expects first value to be less than second.
    /// Formats values with decimals in failure message.
    function assertLtDecimal(int256 left, int256 right, uint256 decimals) external pure;

    /// Compares two `int256` values. Expects first value to be less than second.
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
    function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;

    /// Compares two `uint256` values. Expects first value to be less than second.
    function assertLt(uint256 left, uint256 right) external pure;

    /// Compares two `uint256` values. Expects first value to be less than second.
    /// Includes error message into revert string on failure.
    function assertLt(uint256 left, uint256 right, string calldata error) external pure;

    /// Compares two `int256` values. Expects first value to be less than second.
    function assertLt(int256 left, int256 right) external pure;

    /// Compares two `int256` values. Expects first value to be less than second.
    /// Includes error message into revert string on failure.
    function assertLt(int256 left, int256 right, string calldata error) external pure;

    /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message.
    function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure;

    /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message.
    /// Includes error message into revert string on failure.
    function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;

    /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message.
    function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) external pure;

    /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message.
    /// Includes error message into revert string on failure.
    function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;

    /// Asserts that two `bool` values are not equal.
    function assertNotEq(bool left, bool right) external pure;

    /// Asserts that two `bool` values are not equal and includes error message into revert string on failure.
    function assertNotEq(bool left, bool right, string calldata error) external pure;

    /// Asserts that two `string` values are not equal.
    function assertNotEq(string calldata left, string calldata right) external pure;

    /// Asserts that two `string` values are not equal and includes error message into revert string on failure.
    function assertNotEq(string calldata left, string calldata right, string calldata error) external pure;

    /// Asserts that two `bytes` values are not equal.
    function assertNotEq(bytes calldata left, bytes calldata right) external pure;

    /// Asserts that two `bytes` values are not equal and includes error message into revert string on failure.
    function assertNotEq(bytes calldata left, bytes calldata right, string calldata error) external pure;

    /// Asserts that two arrays of `bool` values are not equal.
    function assertNotEq(bool[] calldata left, bool[] calldata right) external pure;

    /// Asserts that two arrays of `bool` values are not equal and includes error message into revert string on failure.
    function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure;

    /// Asserts that two arrays of `uint256` values are not equal.
    function assertNotEq(uint256[] calldata left, uint256[] calldata right) external pure;

    /// Asserts that two arrays of `uint256` values are not equal and includes error message into revert string on failure.
    function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure;

    /// Asserts that two arrays of `int256` values are not equal.
    function assertNotEq(int256[] calldata left, int256[] calldata right) external pure;

    /// Asserts that two arrays of `int256` values are not equal and includes error message into revert string on failure.
    function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure;

    /// Asserts that two `uint256` values are not equal.
    function assertNotEq(uint256 left, uint256 right) external pure;

    /// Asserts that two arrays of `address` values are not equal.
    function assertNotEq(address[] calldata left, address[] calldata right) external pure;

    /// Asserts that two arrays of `address` values are not equal and includes error message into revert string on failure.
    function assertNotEq(address[] calldata left, address[] calldata right, string calldata error) external pure;

    /// Asserts that two arrays of `bytes32` values are not equal.
    function assertNotEq(bytes32[] calldata left, bytes32[] calldata right) external pure;

    /// Asserts that two arrays of `bytes32` values are not equal and includes error message into revert string on failure.
    function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure;

    /// Asserts that two arrays of `string` values are not equal.
    function assertNotEq(string[] calldata left, string[] calldata right) external pure;

    /// Asserts that two arrays of `string` values are not equal and includes error message into revert string on failure.
    function assertNotEq(string[] calldata left, string[] calldata right, string calldata error) external pure;

    /// Asserts that two arrays of `bytes` values are not equal.
    function assertNotEq(bytes[] calldata left, bytes[] calldata right) external pure;

    /// Asserts that two arrays of `bytes` values are not equal and includes error message into revert string on failure.
    function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure;

    /// Asserts that two `uint256` values are not equal and includes error message into revert string on failure.
    function assertNotEq(uint256 left, uint256 right, string calldata error) external pure;

    /// Asserts that two `int256` values are not equal.
    function assertNotEq(int256 left, int256 right) external pure;

    /// Asserts that two `int256` values are not equal and includes error message into revert string on failure.
    function assertNotEq(int256 left, int256 right, string calldata error) external pure;

    /// Asserts that two `address` values are not equal.
    function assertNotEq(address left, address right) external pure;

    /// Asserts that two `address` values are not equal and includes error message into revert string on failure.
    function assertNotEq(address left, address right, string calldata error) external pure;

    /// Asserts that two `bytes32` values are not equal.
    function assertNotEq(bytes32 left, bytes32 right) external pure;

    /// Asserts that two `bytes32` values are not equal and includes error message into revert string on failure.
    function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure;

    /// Asserts that the given condition is true.
    function assertTrue(bool condition) external pure;

    /// Asserts that the given condition is true and includes error message into revert string on failure.
    function assertTrue(bool condition, string calldata error) external pure;

    /// 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 as structs.
    function rpcUrlStructs() external view returns (Rpc[] memory urls);

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

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

    // ======== Toml ========

    /// Checks if `key` exists in a TOML table.
    function keyExistsToml(string calldata toml, string calldata key) external view returns (bool);

    /// Parses a string of TOML data at `key` and coerces it to `address`.
    function parseTomlAddress(string calldata toml, string calldata key) external pure returns (address);

    /// Parses a string of TOML data at `key` and coerces it to `address[]`.
    function parseTomlAddressArray(string calldata toml, string calldata key)
        external
        pure
        returns (address[] memory);

    /// Parses a string of TOML data at `key` and coerces it to `bool`.
    function parseTomlBool(string calldata toml, string calldata key) external pure returns (bool);

    /// Parses a string of TOML data at `key` and coerces it to `bool[]`.
    function parseTomlBoolArray(string calldata toml, string calldata key) external pure returns (bool[] memory);

    /// Parses a string of TOML data at `key` and coerces it to `bytes`.
    function parseTomlBytes(string calldata toml, string calldata key) external pure returns (bytes memory);

    /// Parses a string of TOML data at `key` and coerces it to `bytes32`.
    function parseTomlBytes32(string calldata toml, string calldata key) external pure returns (bytes32);

    /// Parses a string of TOML data at `key` and coerces it to `bytes32[]`.
    function parseTomlBytes32Array(string calldata toml, string calldata key)
        external
        pure
        returns (bytes32[] memory);

    /// Parses a string of TOML data at `key` and coerces it to `bytes[]`.
    function parseTomlBytesArray(string calldata toml, string calldata key) external pure returns (bytes[] memory);

    /// Parses a string of TOML data at `key` and coerces it to `int256`.
    function parseTomlInt(string calldata toml, string calldata key) external pure returns (int256);

    /// Parses a string of TOML data at `key` and coerces it to `int256[]`.
    function parseTomlIntArray(string calldata toml, string calldata key) external pure returns (int256[] memory);

    /// Returns an array of all the keys in a TOML table.
    function parseTomlKeys(string calldata toml, string calldata key) external pure returns (string[] memory keys);

    /// Parses a string of TOML data at `key` and coerces it to `string`.
    function parseTomlString(string calldata toml, string calldata key) external pure returns (string memory);

    /// Parses a string of TOML data at `key` and coerces it to `string[]`.
    function parseTomlStringArray(string calldata toml, string calldata key) external pure returns (string[] memory);

    /// Parses a string of TOML data at `key` and coerces it to `uint256`.
    function parseTomlUint(string calldata toml, string calldata key) external pure returns (uint256);

    /// Parses a string of TOML data at `key` and coerces it to `uint256[]`.
    function parseTomlUintArray(string calldata toml, string calldata key) external pure returns (uint256[] memory);

    /// ABI-encodes a TOML table.
    function parseToml(string calldata toml) external pure returns (bytes memory abiEncodedData);

    /// ABI-encodes a TOML table at `key`.
    function parseToml(string calldata toml, string calldata key) external pure returns (bytes memory abiEncodedData);

    /// Takes serialized JSON, converts to TOML and write a serialized TOML to a file.
    function writeToml(string calldata json, string calldata path) external;

    /// Takes serialized JSON, converts to TOML and write a serialized TOML table to an **existing** TOML file, replacing a value with key = <value_key.>
    /// This is useful to replace a specific value of a TOML file, without having to parse the entire thing.
    function writeToml(string calldata json, string calldata path, string calldata valueKey) external;

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

    /// 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 the default CREATE2 deployer.
    function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) external pure returns (address);

    /// 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);

    /// 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);

    /// 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);

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

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

    /// Returns ENS namehash for provided string.
    function ensNamehash(string calldata name) external pure returns (bytes32);

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

    /// Get a `Wallet`'s nonce.
    function getNonce(Wallet calldata wallet) external returns (uint64 nonce);

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

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

    /// Signs data with a `Wallet`.
    function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s);

    /// Encodes a `bytes` value to a base64url string.
    function toBase64URL(bytes calldata data) external pure returns (string memory);

    /// Encodes a `string` value to a base64url string.
    function toBase64URL(string calldata data) external pure returns (string memory);

    /// Encodes a `bytes` value to a base64 string.
    function toBase64(bytes calldata data) external pure returns (string memory);

    /// Encodes a `string` value to a base64 string.
    function toBase64(string calldata data) external pure returns (string memory);
}

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

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

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

    /// Sets `block.blobbasefee`
    function blobBaseFee(uint256 newBlobBaseFee) external;

    /// Sets the blobhashes in the transaction.
    /// Not available on EVM versions before Cancun.
    /// If used on unsupported EVM versions it will revert.
    function blobhashes(bytes32[] calldata hashes) external;

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

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

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

    /// 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 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 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 the latest block and returns the identifier of the fork.
    function createSelectFork(string calldata urlOrAlias) 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);

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

    /// Removes the snapshot with the given ID created by `snapshot`.
    /// Takes the snapshot ID to delete.
    /// Returns `true` if the snapshot was successfully deleted.
    /// Returns `false` if the snapshot does not exist.
    function deleteSnapshot(uint256 snapshotId) external returns (bool success);

    /// Removes _all_ snapshots previously created by `snapshot`.
    function deleteSnapshots() external;

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

    /// Dump a genesis JSON file's `allocs` to disk.
    function dumpState(string calldata pathToStateJson) external;

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

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

    /// Gets the blockhashes from the current transaction.
    /// Not available on EVM versions before Cancun.
    /// If used on unsupported EVM versions it will revert.
    function getBlobhashes() external view returns (bytes32[] memory hashes);

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

    /// Load a genesis JSON file's `allocs` into the in-memory revm state.
    function loadAllocs(string calldata pathToAllocsJson) 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;

    /// See `makePersistent(address)`.
    function makePersistent(address account0, address account1) external;

    /// See `makePersistent(address)`.
    function makePersistent(address account0, address account1, address account2) external;

    /// See `makePersistent(address)`.
    function makePersistent(address[] calldata accounts) 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;

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

    /// Sets the *next* call's `msg.sender` to be the input address.
    function prank(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 `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.prevrandao`.
    /// Not available on EVM versions before Paris. Use `difficulty` instead.
    /// If used on unsupported EVM versions it will revert.
    function prevrandao(uint256 newPrevrandao) 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);

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

    /// Revert the state of the EVM to a previous snapshot
    /// Takes the snapshot ID to revert to.
    /// Returns `true` if the snapshot was successfully reverted.
    /// Returns `false` if the snapshot does not exist.
    /// **Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteSnapshot`.
    function revertTo(uint256 snapshotId) external returns (bool success);

    /// Revert the state of the EVM to a previous snapshot and automatically deletes the snapshots
    /// Takes the snapshot ID to revert to.
    /// Returns `true` if the snapshot was successfully reverted and deleted.
    /// Returns `false` if the snapshot does not exist.
    function revertToAndDelete(uint256 snapshotId) external returns (bool success);

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

    /// See `revokePersistent(address)`.
    function revokePersistent(address[] calldata accounts) external;

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

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

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

    /// 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);

    /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called.
    function startPrank(address msgSender) 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;

    /// Stores a value to an address' storage slot.
    function store(address target, bytes32 slot, bytes32 value) 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;

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

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

    // ======== Testing ========

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

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

    /// 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 with any revert data.
    function expectRevert() external;

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

    /// Expects an error on next call that exactly matches the revert data.
    function expectRevert(bytes calldata revertData) 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;

    /// Stops all safe memory expectation in the current subcontext.
    function stopExpectSafeMemory() external;
}

// 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/utils/WardsAbstract.sol

interface WardsAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) 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 {
    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(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(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(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(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(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;
    }
}

// src/dependencies/chief-migration/MigrationInstance.sol
// SPDX-FileCopyrightText: © 2025 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 MigrationInstance {
    address chief;
    address voteDelegateFactory;
    address mkrSky;
    address skyOsm;
    address lsskyUsdsFarm;
    LockstakeInstance lockstakeInstance;
}

// 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());
    }
}

// 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/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 mint(address, uint256) external;
}

interface MkrSkyLike_0 {
    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);
    function totalSupply() external view returns (uint256);
}

interface MkrAuthorityLike {
    function deny(address) external;
}

library SkyInit {

    // Note that we assume the fee is 0 initially, hence we don't set it explicitly
    function updateMkrSky(
        DssInstance memory dss,
        address mkrSky
    ) internal {
        address oldMkrSky = dss.chainlog.getAddress("MKR_SKY");
        address mkr  = MkrSkyLike_0(oldMkrSky).mkr();
        address sky  = MkrSkyLike_0(oldMkrSky).sky();
        uint256 rate = MkrSkyLike_0(oldMkrSky).rate();

        require(MkrSkyLike_0(mkrSky).mkr()  == mkr);
        require(MkrSkyLike_0(mkrSky).sky()  == sky);
        require(MkrSkyLike_0(mkrSky).rate() == rate);

        // Block the sky=>mkr direction for the old converter
        MkrAuthorityLike(MkrLike(mkr).authority()).deny(oldMkrSky);

        // Mint SKY to facilitate conversions
        SkyLike(sky).mint(mkrSky, MkrLike(mkr).totalSupply() * rate);

        dss.chainlog.setAddress("MKR_SKY_LEGACY", oldMkrSky);
        dss.chainlog.setAddress("MKR_SKY", mkrSky);
    }
}

// src/dependencies/lockstake/LockstakeInit.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 LockstakeSkyLike {
    function rely(address) external;
}

interface LockstakeEngineLike {
    function voteDelegateFactory() external view returns (address);
    function vat() external view returns (address);
    function usdsJoin() external view returns (address);
    function usds() external view returns (address);
    function ilk() external view returns (bytes32);
    function sky() external view returns (address);
    function lssky() external view returns (address);
    function fee() external view returns (uint256);
    function rely(address) external;
    function file(bytes32, address) external;
    function addFarm(address) external;
}

interface LockstakeClipperLike {
    function vat() external view returns (address);
    function dog() external view returns (address);
    function spotter() external view returns (address);
    function engine() external view returns (address);
    function ilk() external view returns (bytes32);
    function rely(address) external;
    function file(bytes32, address) external;
    function file(bytes32, uint256) external;
    function upchost() external;
}

interface LockstakeMigratorLike {
    function oldEngine() external view returns (address);
    function newEngine() external view returns (address);
    function mkrSky() external view returns (address);
    function flash() external view returns (address);
}

interface PipLike {
    function kiss(address) external;
    function rely(address) external;
}

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

interface AutoLineLike {
    function ilks(bytes32) external returns (uint256, uint256, uint48, uint48, uint48);
    function remIlk(bytes32) external;
}

interface OsmMomLike {
    function setOsm(bytes32, address) external;
}

interface LineMomLike {
    function addIlk(bytes32) external;
}

interface ClipperMomLike {
    function setPriceTolerance(address, uint256) external;
}

interface StakingRewardsLike_1 {
    function stakingToken() external view returns (address);
}

interface IlkRegistryLike {
    function put(
        bytes32 _ilk,
        address _join,
        address _gem,
        uint256 _dec,
        uint256 _class,
        address _pip,
        address _xlip,
        string memory _name,
        string memory _symbol
    ) external;
}

struct LockstakeConfig {
    bytes32   ilk;
    address[] farms;
    uint256   fee;
    uint256   dust;
    uint256   duty;
    uint256   mat;
    uint256   buf;
    uint256   tail;
    uint256   cusp;
    uint256   chip;
    uint256   tip;
    uint256   stopped;
    uint256   chop;
    uint256   hole;
    uint256   tau;
    uint256   cut;
    uint256   step;
    bool      lineMom;
    uint256   tolerance;
    string    name;
    string    symbol;
}

struct StackExtension {
    LockstakeSkyLike lssky;
    LockstakeEngineLike engine;
    LockstakeClipperLike clipper;
    CalcLike calc;
    LockstakeMigratorLike migrator;
    LockstakeEngineLike oldEngine;
    AutoLineLike autoLine;
    address sky;
}

library LockstakeInit {
    uint256 constant internal RATES_ONE_HUNDRED_PCT = 1000000021979553151239153027;
    uint256 constant internal WAD = 10**18;
    uint256 constant internal RAY = 10**27;
    uint256 constant internal RAD = 10**45;

    function initLockstake(
        DssInstance        memory dss,
        LockstakeInstance  memory lockstakeInstance,
        LockstakeConfig    memory cfg
    ) internal {
        StackExtension memory se = StackExtension ({
            lssky:     LockstakeSkyLike(lockstakeInstance.lssky),
            engine:    LockstakeEngineLike(lockstakeInstance.engine),
            clipper:   LockstakeClipperLike(lockstakeInstance.clipper),
            calc:      CalcLike(lockstakeInstance.clipperCalc),
            migrator:  LockstakeMigratorLike(lockstakeInstance.migrator),
            oldEngine: LockstakeEngineLike(dss.chainlog.getAddress("LOCKSTAKE_ENGINE")),
            autoLine:  AutoLineLike(dss.chainlog.getAddress("MCD_IAM_AUTO_LINE")),
            sky:       dss.chainlog.getAddress("SKY")
        });

        bytes32 oldEngineIlk = se.oldEngine.ilk();

        // Sanity checks
        require(oldEngineIlk                    != cfg.ilk);
        require(se.engine.voteDelegateFactory() == dss.chainlog.getAddress("VOTE_DELEGATE_FACTORY"));
        require(se.engine.vat()                 == address(dss.vat));
        require(se.engine.usdsJoin()            == dss.chainlog.getAddress("USDS_JOIN"));
        require(se.engine.usds()                == dss.chainlog.getAddress("USDS"));
        require(se.engine.ilk()                 == cfg.ilk);
        require(se.engine.sky()                 == se.sky);
        require(se.engine.lssky()               == address(se.lssky));
        require(se.engine.fee()                 == cfg.fee);
        require(se.clipper.ilk()                == cfg.ilk);
        require(se.clipper.vat()                == address(dss.vat));
        require(se.clipper.engine()             == address(se.engine));
        require(se.clipper.dog()                == address(dss.dog));
        require(se.clipper.spotter()            == address(dss.spotter));
        require(se.migrator.oldEngine()         == address(se.oldEngine));
        require(se.migrator.newEngine()         == address(se.engine));
        require(se.migrator.mkrSky()            == dss.chainlog.getAddress("MKR_SKY"));
        require(se.migrator.flash()             == dss.chainlog.getAddress("MCD_FLASH"));
        (,,, uint256 line,) = dss.vat.ilks(cfg.ilk);
        require(line                            == 0);
        (line,,,,) = se.autoLine.ilks(cfg.ilk);
        require(line                            == 0);

        require(cfg.dust <= cfg.hole);
        require(cfg.duty >= RAY && cfg.duty <= RATES_ONE_HUNDRED_PCT);
        require(cfg.mat >= RAY && cfg.mat < 10 * RAY);
        require(cfg.buf >= RAY && cfg.buf < 10 * RAY);
        require(cfg.cusp < RAY);
        require(cfg.chip < WAD);
        require(cfg.tip <= 1_000 * RAD);
        require(cfg.chop >= WAD && cfg.chop < 2 * WAD);
        require(cfg.tolerance < RAY);

        se.oldEngine.rely(address(se.migrator));

        dss.vat.file(oldEngineIlk, "line", 0); // Clean only ilk line, as there will probably be existing debt. Line can be adjusted in a later stage.
        se.autoLine.remIlk(oldEngineIlk);

        dss.vat.init(cfg.ilk);
        dss.vat.file(cfg.ilk, "dust", cfg.dust);
        dss.vat.rely(address(se.engine));
        dss.vat.rely(address(se.clipper));
        dss.vat.rely(address(se.migrator));

        dss.jug.init(cfg.ilk);
        dss.jug.file(cfg.ilk, "duty", cfg.duty);

        address pip = dss.chainlog.getAddress("PIP_SKY");
        address clipperMom = dss.chainlog.getAddress("CLIPPER_MOM");
        PipLike(pip).kiss(address(dss.spotter));
        PipLike(pip).kiss(address(se.clipper));
        PipLike(pip).kiss(clipperMom);
        PipLike(pip).kiss(address(dss.end));
        // This assumes pip is a standard Osm sourced by a Median
        {
        address osmMom = dss.chainlog.getAddress("OSM_MOM");
        PipLike(pip).rely(osmMom);
        OsmMomLike(osmMom).setOsm(cfg.ilk, pip);
        }

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

        dss.dog.file(cfg.ilk, "clip", address(se.clipper));
        dss.dog.file(cfg.ilk, "chop", cfg.chop);
        dss.dog.file(cfg.ilk, "hole", cfg.hole);
        dss.dog.rely(address(se.clipper));

        se.lssky.rely(address(se.engine));

        se.engine.file("jug", address(dss.jug));
        for (uint256 i = 0; i < cfg.farms.length; i++) {
            require(StakingRewardsLike_1(cfg.farms[i]).stakingToken() == lockstakeInstance.lssky);
            se.engine.addFarm(cfg.farms[i]);
        }
        se.engine.rely(address(se.clipper));

        se.clipper.file("buf",     cfg.buf);
        se.clipper.file("tail",    cfg.tail);
        se.clipper.file("cusp",    cfg.cusp);
        se.clipper.file("chip",    cfg.chip);
        se.clipper.file("tip",     cfg.tip);
        se.clipper.file("stopped", cfg.stopped);
        se.clipper.file("vow",     address(dss.vow));
        se.clipper.file("calc",    address(se.calc));
        se.clipper.upchost();
        se.clipper.rely(address(dss.dog));
        se.clipper.rely(address(dss.end));
        se.clipper.rely(clipperMom);

        if (cfg.tau  > 0) se.calc.file("tau",  cfg.tau);
        if (cfg.cut  > 0) se.calc.file("cut",  cfg.cut);
        if (cfg.step > 0) se.calc.file("step", cfg.step);

        if (cfg.lineMom) {
            LineMomLike(dss.chainlog.getAddress("LINE_MOM")).addIlk(cfg.ilk);
        }

        if (cfg.tolerance > 0) {
            ClipperMomLike(clipperMom).setPriceTolerance(address(se.clipper), cfg.tolerance);
        }

        IlkRegistryLike(dss.chainlog.getAddress("ILK_REGISTRY")).put(
            cfg.ilk,
            address(0),
            se.sky,
            18,
            7, // New class
            pip,
            address(se.clipper),
            cfg.name,
            cfg.symbol
        );

        dss.chainlog.setAddress("LOCKSTAKE_MKR_OLD_V1",       dss.chainlog.getAddress("LOCKSTAKE_MKR"));
        dss.chainlog.setAddress("LOCKSTAKE_ENGINE_OLD_V1",    address(se.oldEngine));
        dss.chainlog.setAddress("LOCKSTAKE_CLIP_OLD_V1",      dss.chainlog.getAddress("LOCKSTAKE_CLIP"));
        dss.chainlog.setAddress("LOCKSTAKE_CLIP_CALC_OLD_V1", dss.chainlog.getAddress("LOCKSTAKE_CLIP_CALC"));
        dss.chainlog.removeAddress("LOCKSTAKE_MKR");

        dss.chainlog.setAddress("LOCKSTAKE_SKY",       address(se.lssky));
        dss.chainlog.setAddress("LOCKSTAKE_ENGINE",    address(se.engine));
        dss.chainlog.setAddress("LOCKSTAKE_CLIP",      address(se.clipper));
        dss.chainlog.setAddress("LOCKSTAKE_CLIP_CALC", address(se.calc));
        dss.chainlog.setAddress("LOCKSTAKE_MIGRATOR",  address(se.migrator));
    }
}

// src/dependencies/chief-migration/MigrationInit.sol
// SPDX-FileCopyrightText: © 2025 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 ChiefLike {
    function gov() external view returns (address);
    function maxYays() external view returns (uint256);
    function launchThreshold() external view returns (uint256);
    function liftCooldown() external view returns (uint256);
}

interface VoteDelegateFactoryLike {
    function chief() external view returns (address);
    function polling() external view returns (address);
}

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

interface StakingRewardsLike_2 {
    function stakingToken() external view returns (address);
    function rewardsToken() external view returns (address);
    function setRewardsDuration(uint256) external;
}

interface AuthedLike {
    function setAuthority(address) external;
}

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

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

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

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

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

struct MigrationConfig {
    uint256 maxYays;
    uint256 launchThreshold;
    uint256 liftCooldown;
    address skyOracle;
    uint256 rewardsDuration;
    LockstakeConfig lockstakeConfig;
}

library MigrationInit {
    function initMigration(
        DssInstance       memory dss,
        MigrationInstance memory inst,
        MigrationConfig   memory cfg
    ) internal {
        address sky = dss.chainlog.getAddress("SKY");

        // Sanity checks
        require(ChiefLike(inst.chief).gov()             == sky);
        require(ChiefLike(inst.chief).maxYays()         == cfg.maxYays);
        require(ChiefLike(inst.chief).launchThreshold() == cfg.launchThreshold);
        require(ChiefLike(inst.chief).liftCooldown()    == cfg.liftCooldown);

        require(VoteDelegateFactoryLike(inst.voteDelegateFactory).chief()   == inst.chief);
        require(VoteDelegateFactoryLike(inst.voteDelegateFactory).polling() == VoteDelegateFactoryLike(dss.chainlog.getAddress("VOTE_DELEGATE_FACTORY")).polling());

        require(OsmLike(inst.skyOsm).src() == cfg.skyOracle);

        require(StakingRewardsLike_2(inst.lsskyUsdsFarm).stakingToken() == inst.lockstakeInstance.lssky);
        require(StakingRewardsLike_2(inst.lsskyUsdsFarm).rewardsToken() == dss.chainlog.getAddress("USDS"));

        // Chief migration
        // Note: this list does not include the Spark FREEZER_MOM, which authority should be changed in a Spark sub-spell
        AuthedLike(dss.chainlog.getAddress("MCD_PAUSE")).setAuthority(inst.chief);
        AuthedLike(dss.chainlog.getAddress("SPLITTER_MOM")).setAuthority(inst.chief);
        AuthedLike(dss.chainlog.getAddress("OSM_MOM")).setAuthority(inst.chief);
        AuthedLike(dss.chainlog.getAddress("CLIPPER_MOM")).setAuthority(inst.chief);
        AuthedLike(dss.chainlog.getAddress("DIRECT_MOM")).setAuthority(inst.chief);
        AuthedLike(dss.chainlog.getAddress("STARKNET_ESCROW_MOM")).setAuthority(inst.chief);
        AuthedLike(dss.chainlog.getAddress("LINE_MOM")).setAuthority(inst.chief);
        AuthedLike(dss.chainlog.getAddress("LITE_PSM_MOM")).setAuthority(inst.chief);
        AuthedLike(dss.chainlog.getAddress("SPBEAM_MOM")).setAuthority(inst.chief);
        dss.chainlog.setAddress("MCD_ADM", inst.chief);

        // New VoteDelegate factory (must be done before initLockstake)
        dss.chainlog.setAddress("VOTE_DELEGATE_FACTORY_LEGACY", dss.chainlog.getAddress("VOTE_DELEGATE_FACTORY"));
        dss.chainlog.setAddress("VOTE_DELEGATE_FACTORY", inst.voteDelegateFactory);

        // New MKR to SKY migrator (must be done before initLockstake)
        SkyInit.updateMkrSky(dss, inst.mkrSky);

        // Set the new SKY oracle in the flapper
        // Note: we assume the current flapper is given permission to read from the oracle
        FlapperLike(dss.chainlog.getAddress("MCD_FLAP")).file("pip", cfg.skyOracle);
        dss.chainlog.setAddress("FLAP_SKY_ORACLE", cfg.skyOracle);

        // New SKY OSM (must be done before initLockstake)
        // Note: we assume the OSM is given permission to read from the oracle
        // Note: the rest of the OSM setup is done in initLockstake below
        // Note: PIP_MKR is still used in the old lockstake, so we don't remove it yet from the chainlog
        dss.chainlog.setAddress("PIP_SKY", inst.skyOsm);

        // Init new farm to be used in lockstake
        // Note: we assume that if splitter.burn, splitter.hop, vow.bump or vow.hump are modified it is done outside this lib
        // Note: we assume cfg.rewardsDuration to be same as the final value of splitter.hop for the spell
        address splitter = dss.chainlog.getAddress("MCD_SPLIT");
        StakingRewardsInit.init(inst.lsskyUsdsFarm, StakingRewardsInitParams({dist: splitter}));
        StakingRewardsLike_2(inst.lsskyUsdsFarm).setRewardsDuration(cfg.rewardsDuration);
        SplitterLike(splitter).file("farm", inst.lsskyUsdsFarm);
        dss.chainlog.setAddress("REWARDS_LSSKY_USDS", inst.lsskyUsdsFarm);
        dss.chainlog.setAddress("REWARDS_LSMKR_USDS_LEGACY", dss.chainlog.getAddress("REWARDS_LSMKR_USDS"));
        dss.chainlog.removeAddress("REWARDS_LSMKR_USDS");

        // Lockstake Migration
        LockstakeInit.initLockstake(dss, inst.lockstakeInstance, cfg.lockstakeConfig);

        // MKR flops are turned off
        VowLike(dss.chainlog.getAddress("MCD_VOW")).file("sump", type(uint256).max);

        // ESM full disablement
        EsmLike(dss.chainlog.getAddress("MCD_ESM")).file("min", type(uint256).max);

        // Handle more chainlog keys (should be done last as MCD_GOV is assumed as MKR above)
        dss.chainlog.setAddress("MKR", dss.chainlog.getAddress("MCD_GOV"));
        dss.chainlog.setAddress("MCD_GOV", sky);
        dss.chainlog.removeAddress("MCD_GOV_ACTIONS");
        dss.chainlog.setAddress("MKR_GUARD", dss.chainlog.getAddress("GOV_GUARD"));
        dss.chainlog.removeAddress("GOV_GUARD");
    }
}

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

// Note: code matches https://github.com/makerdao/chief-migration/blob/e4a820483694f015a2daf8b1dccc5548036d94d4/deploy/MigrationInit.sol

// Note: code matches https://github.com/makerdao/lockstake/blob/9cb25125bceb488f39dc4ddd3b54c05217a260d1/deploy/LockstakeInstance.sol

// Note: code matches https://github.com/makerdao/lockstake/blob/9cb25125bceb488f39dc4ddd3b54c05217a260d1/deploy/LockstakeInit.sol

interface ProxyLike {
    function exec(address target, bytes calldata args) external payable returns (bytes memory out);
}

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/5ca420d2d2c0ad1a159914a7942eacc8b621ab7d/governance/votes/Executive%20vote%20-%20May%2015%2C%202025.md' -q -O - 2>/dev/null)"
    string public constant override description = "2025-05-15 MakerDAO Executive Spell | Hash: 0x59d2dd09c95fe525067a78e1df77fdc95dafa4da4c9c1e5dd1a783af1bb88e68";

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

    // ---------- 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 TWENTY_PCT_RATE = 1000000005781378656804591712;

    // ---------- Math ----------
    uint256 internal constant WAD = 10 ** 18;
    uint256 internal constant RAY = 10 ** 27;
    uint256 internal constant RAD = 10 ** 45;

    // ---------- Contracts ----------
    address internal immutable CLIPPER_MOM          = DssExecLib.clipperMom();
    address internal constant MCD_ADM               = 0x929d9A1435662357F54AdcF64DcEE4d6b867a6f9;
    address internal constant VOTE_DELEGATE_FACTORY = 0x4Cf3DaeFA2683Cd18df00f7AFF5169C00a9EccD5;
    address internal constant MKR_SKY               = 0xA1Ea1bA18E88C381C724a75F23a130420C403f9a;
    address internal constant PIP_SKY               = 0x511485bBd96e7e3a056a8D1b84C5071071C52D6F;
    address internal constant REWARDS_LSSKY_USDS    = 0x38E4254bD82ED5Ee97CD1C4278FAae748d998865;
    address internal constant LOCKSTAKE_SKY         = 0xf9A9cfD3229E985B91F99Bc866d42938044FFa1C;
    address internal constant LOCKSTAKE_ENGINE      = 0xCe01C90dE7FD1bcFa39e237FE6D8D9F569e8A6a3;
    address internal constant LOCKSTAKE_CLIP        = 0x35526314F18FeB5b7F124e40D6A99d64F7D7e89a;
    address internal constant LOCKSTAKE_CLIP_CALC   = 0xB8f8c7caabFa320717E3e848948450e120F0D9BB;
    address internal constant LOCKSTAKE_MIGRATOR    = 0x473d777f608C3C24B441AB6bD4bBcA6b7F9AF90B;
    address internal constant FLAP_SKY_ORACLE       = 0xc2ffbbDCCF1466Eb8968a846179191cb881eCdff;
    address internal constant MCD_PROTEGO           = 0x5C9c3cb0490938c9234ABddeD37a191576ED8624;

    // ---------- Spark Proxy Spell ----------
    // Spark Proxy: https://github.com/marsfoundation/sparklend-deployments/blob/bba4c57d54deb6a14490b897c12a949aa035a99b/script/output/1/primary-sce-latest.json#L2
    address internal constant SPARK_PROXY = 0x3300f198988e4C9C63F75dF86De36421f06af8c4;
    address internal constant SPARK_SPELL = 0xC40611AC4Fff8572Dc5F02A238176edCF15Ea7ba;

    function actions() public override {
        // ---------- Initialize chief migration by calling MigrationInit.initMigration with the following parameters: ----------
        // Forum: https://forum.sky.money/t/atlas-edit-weekly-cycle-proposal-week-of-may-5-2025/26319
        // Atlas: https://sky-atlas.powerhouse.io/A.4.1.2.1_MKR_To_SKY_Upgrade/d5af8504-ddd6-416d-8429-897497b072dc%7Cb341f4c0b834
        // Forum: https://forum.sky.money/t/technical-scope-of-the-chief-migration/26361
        // Forum: https://forum.sky.money/t/technical-scope-of-the-chief-migration/26361/3
        // Forum: https://forum.sky.money/t/atlas-edit-weekly-cycle-proposal-week-of-may-12-2025/26364
        // Poll: https://vote.makerdao.com/polling/QmTVd4iq

        // Note: DssInstance is required by the MigrationInit library below
        DssInstance memory dss = MCD.loadFromChainlog(DssExecLib.LOG);

        // Note: `farms` array is required by the LockstakeConfig below
        address[] memory farms = new address[](1);
        farms[0] = REWARDS_LSSKY_USDS;

        MigrationInit.initMigration(

            // Note: this init library requires DssInstance
            dss,

            MigrationInstance({

                // inst.chief: 0x929d9A1435662357F54AdcF64DcEE4d6b867a6f9
                chief:               MCD_ADM,

                // inst.voteDelegateFactory: 0x4Cf3DaeFA2683Cd18df00f7AFF5169C00a9EccD5
                voteDelegateFactory: VOTE_DELEGATE_FACTORY,

                // inst.mkrSky: 0xA1Ea1bA18E88C381C724a75F23a130420C403f9a
                mkrSky:              MKR_SKY,

                // inst.skyOsm: 0x511485bBd96e7e3a056a8D1b84C5071071C52D6F
                skyOsm:              PIP_SKY,

                // inst.lsskyUsdsFarm: 0x38E4254bD82ED5Ee97CD1C4278FAae748d998865
                lsskyUsdsFarm:       REWARDS_LSSKY_USDS,

                lockstakeInstance: LockstakeInstance({

                    // inst.lockstakeInstance.lssky: 0xf9A9cfD3229E985B91F99Bc866d42938044FFa1C
                    lssky:           LOCKSTAKE_SKY,

                    // inst.lockstakeInstance.engine: 0xCe01C90dE7FD1bcFa39e237FE6D8D9F569e8A6a3
                    engine:          LOCKSTAKE_ENGINE,

                    // inst.lockstakeInstance.clipper:  0x35526314F18FeB5b7F124e40D6A99d64F7D7e89a
                    clipper:         LOCKSTAKE_CLIP,

                    // inst.lockstakeInstance.clipperCalc: 0xB8f8c7caabFa320717E3e848948450e120F0D9BB
                    clipperCalc:     LOCKSTAKE_CLIP_CALC,

                    // inst.lockstakeInstance.migrator: 0x473d777f608C3C24B441AB6bD4bBcA6b7F9AF90B
                    migrator:        LOCKSTAKE_MIGRATOR
                })
            }),

            MigrationConfig({

                // cfg.maxYays: 5
                maxYays:             5,

                // cfg.launchThreshold 2,400,000,000 SKY (equivalent to 100,000 MKR)
                launchThreshold:     2_400_000_000 * WAD,

                // cfg.liftCooldown: 10 blocks
                liftCooldown:        10,

                // cfg.skyOracle: 0xc2ffbbDCCF1466Eb8968a846179191cb881eCdff
                skyOracle:           FLAP_SKY_ORACLE,

                // cfg.rewardsDuration: equal to the splitter.hop (1,728 seconds)
                rewardsDuration:     1_728 seconds,

                lockstakeConfig: LockstakeConfig({

                    // cfg.lockstakeConfig.ilk: "LSEV2-SKY-A"
                    ilk :            "LSEV2-SKY-A",

                    // cfg.lockstakeConfig.farms: array [StakingRewards: 0x38E4254bD82ED5Ee97CD1C4278FAae748d998865]
                    farms:           farms,

                    // cfg.lockstakeConfig.fee: 0
                    fee:             0,

                    // cfg.lockstakeConfig.dust: 30,000
                    dust:            30_000 * RAD,

                    // cfg.lockstakeConfig.duty: 20%
                    duty:            TWENTY_PCT_RATE,

                    // cfg.lockstakeConfig.mat: 125%
                    mat:             125 * RAY / 100,

                    // cfg.lockstakeConfig.buf: 120%
                    buf:             120 * RAY / 100,

                    // cfg.lockstakeConfig.tail: 6,000 seconds
                    tail:            6_000 seconds,

                    // cfg.lockstakeConfig.cusp: 40%
                    cusp:            40 * RAY / 100,

                    // cfg.lockstakeConfig.chip: 0.1%
                    chip:            1 * WAD / 1000,

                    // cfg.lockstakeConfig.tip: 300 USDS
                    tip:             300 * RAD,

                    // cfg.lockstakeConfig.stopped: 3
                    stopped:         3,

                    // cfg.lockstakeConfig.chop: 13%
                    chop:            113 * WAD / 100,

                    // cfg.lockstakeConfig.hole: 250,000
                    hole:            250_000 * RAD,

                    // cfg.lockstakeConfig.tau: 0 days
                    tau:             0,

                    // cfg.lockstakeConfig.cut: 0.99
                    cut:             99 * RAY / 100,

                    // cfg.lockstakeConfig.step: 60 seconds
                    step:            60 seconds,

                    // cfg.lockstakeConfig.lineMom: true (as "added to LINE_MOM")
                    lineMom:         true,

                    // cfg.lockstakeConfig.tolerance: 0.5
                    tolerance:       5 * RAY / 10,

                    // cfg.lockstakeConfig.name: LockstakeSky
                    name:            "LockstakeSky",

                    // cfg.lockstakeConfig.symbol: lsSKY
                    symbol:          "lsSKY"
                })
            })
        );

        // ---------- Remove CLIPPER_MOM Access ----------
        // Forum: https://forum.sky.money/t/atlas-edit-weekly-cycle-proposal-week-of-may-5-2025/26319
        // Atlas: https://sky-atlas.powerhouse.io/A.4.1.2.1_MKR_To_SKY_Upgrade/d5af8504-ddd6-416d-8429-897497b072dc%7Cb341f4c0b834
        // Forum: https://forum.sky.money/t/technical-scope-of-the-chief-migration/26361
        // Forum: https://forum.sky.money/t/technical-scope-of-the-chief-migration/26361/3

        // Deny CLIPPER_MOM from the new LockstakeClipper
        DssExecLib.deauthorize(LOCKSTAKE_CLIP, CLIPPER_MOM);

        // ---------- Add Protego to Chainlog ----------
        // Forum: https://forum.sky.money/t/atlas-edit-weekly-cycle-proposal-week-of-may-5-2025/26319
        // Atlas: https://sky-atlas.powerhouse.io/A.1.9.4.3_Protego/1f1f2ff0-8d73-80be-9ace-f125242ede47%7C0db307588902
        // Forum: https://forum.sky.money/t/technical-scope-of-the-protego-deployment/26365
        // Forum: https://forum.sky.money/t/technical-scope-of-the-protego-deployment/26365/2

        // Add Protego (0x5C9c3cb0490938c9234ABddeD37a191576ED8624) to chainlog with key “MCD_PROTEGO”
        DssExecLib.setChangelogAddress("MCD_PROTEGO", MCD_PROTEGO);

        // Bump chainlog MINOR version
        DssExecLib.setChangelogVersion("1.20.0");

        // ---------- Spark Proxy Spell ----------
        // Forum: https://forum.sky.money/t/atlas-edit-weekly-cycle-proposal-week-of-may-5-2025/26319
        // Atlas: https://sky-atlas.powerhouse.io/A.4.1.2.1_MKR_To_SKY_Upgrade/d5af8504-ddd6-416d-8429-897497b072dc%7Cb341f4c0b834

        // Execute Spark Proxy spell at 0xC40611AC4Fff8572Dc5F02A238176edCF15Ea7ba
        ProxyLike(SPARK_PROXY).exec(SPARK_SPELL, abi.encodeWithSignature("execute()"));
    }
}

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":"action","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cast","outputs":[],"stateMutability":"nonpayable","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":"log","outputs":[{"internalType":"contract Changelog","name":"","type":"address"}],"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 PauseAbstract","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"}]

6101006040523480156200001257600080fd5b50620000224262278d006200013a565b60405162000030906200012c565b604051809103906000f0801580156200004d573d6000803e3d6000fd5b506040516321f8a72160e01b8152684d43445f504155534560b81b600482015273da0ab1e0017debcd72be8599041a2aa3ba7e740f906321f8a72190602401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d0919062000162565b6001600160a01b0390811660e05260c0839052811660a0526040805160048152602481019091526020810180516001600160e01b0316631851865560e21b17905260019062000120908262000239565b503f6080525062000305565b615d8a8062000e1a83390190565b808201808211156200015c57634e487b7160e01b600052601160045260246000fd5b92915050565b6000602082840312156200017557600080fd5b81516001600160a01b03811681146200018d57600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620001bf57607f821691505b602082108103620001e057634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200023457600081815260208120601f850160051c810160208610156200020f5750805b601f850160051c820191505b8181101562000230578281556001016200021b565b5050505b505050565b81516001600160401b0381111562000255576200025562000194565b6200026d81620002668454620001aa565b84620001e6565b602080601f831160018114620002a557600084156200028c5750858301515b600019600386901b1c1916600185901b17855562000230565b600085815260208120601f198616915b82811015620002d657888601518255948401946001909101908401620002b5565b5085821015620002f55787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e051610a8f6200038b600039600081816101cc01528181610434015281816105c7015261066d01526000818161013501526104f901526000818160f6015281816102b001528181610339015281816104610152818161069a01526107360152600081816101850152818161048301526106bc0152610a8f6000f3fe608060405234801561001057600080fd5b50600436106100ce5760003560e01c80637284e4161161008c578063ae8421e111610066578063ae8421e1146101f8578063b0604a2614610205578063f7992d851461020d578063fe7d47bb1461021657600080fd5b80637284e416146101bf5780638456cb59146101c757806396d373e5146101ee57600080fd5b8062a7029b146100d35780630a7a1c4d146100f15780634665096d1461013057806351973ec91461016557806351f91066146101805780636e832f07146101a7575b600080fd5b6100db61021e565b6040516100e891906107f9565b60405180910390f35b6101187f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100e8565b6101577f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016100e8565b61011873da0ab1e0017debcd72be8599041a2aa3ba7e740f81565b6101577f000000000000000000000000000000000000000000000000000000000000000081565b6101af6102ac565b60405190151581526020016100e8565b6100db610335565b6101187f000000000000000000000000000000000000000000000000000000000000000081565b6101f66103bd565b005b6002546101af9060ff1681565b6101f66104f7565b61015760005481565b61015761071b565b6001805461022b90610813565b80601f016020809104026020016040519081016040528092919081815260200182805461025790610813565b80156102a45780601f10610279576101008083540402835291602001916102a4565b820191906000526020600020905b81548152906001019060200180831161028757829003601f168201915b505050505081565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636e832f076040518163ffffffff1660e01b8152600401602060405180830381865afa15801561030c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610330919061084d565b905090565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637284e4166040518163ffffffff1660e01b8152600401600060405180830381865afa158015610395573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261033091908101906108f9565b60025460ff161561040a5760405162461bcd60e51b81526020600482015260126024820152711cdc195b1b0b585b1c9958591e4b58d85cdd60721b60448201526064015b60405180910390fd5b6002805460ff1916600190811790915560005460405163168ccd6760e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263168ccd67926104ad927f0000000000000000000000000000000000000000000000000000000000000000927f000000000000000000000000000000000000000000000000000000000000000092909160040161094a565b6000604051808303816000875af11580156104cc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104f491908101906108f9565b50565b7f00000000000000000000000000000000000000000000000000000000000000004211156105675760405162461bcd60e51b815260206004820152601960248201527f5468697320636f6e7472616374206861732065787069726564000000000000006044820152606401610401565b600054156105c55760405162461bcd60e51b815260206004820152602560248201527f54686973207370656c6c2068617320616c7265616479206265656e2073636865604482015264191d5b195960da1b6064820152608401610401565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636a42b8f86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106479190610a19565b6106519042610a32565b60008190556040516346d2fbbb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916346d2fbbb916106e7917f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009160019160040161094a565b600060405180830381600087803b15801561070157600080fd5b505af1158015610715573d6000803e3d6000fd5b50505050565b60008054604051632fc3ef3b60e21b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063bf0fbcec90602401602060405180830381865afa158015610785573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103309190610a19565b60005b838110156107c45781810151838201526020016107ac565b50506000910152565b600081518084526107e58160208601602086016107a9565b601f01601f19169290920160200192915050565b60208152600061080c60208301846107cd565b9392505050565b600181811c9082168061082757607f821691505b60208210810361084757634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561085f57600080fd5b8151801515811461080c57600080fd5b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156108a0576108a061086f565b604051601f8501601f19908116603f011681019082821181831017156108c8576108c861086f565b816040528093508581528686860111156108e157600080fd5b6108ef8660208301876107a9565b5050509392505050565b60006020828403121561090b57600080fd5b815167ffffffffffffffff81111561092257600080fd5b8201601f8101841361093357600080fd5b61094284825160208401610885565b949350505050565b6001600160a01b03851681526020808201859052608060408301528354600091908290600181811c908281168061098257607f831692505b858310810361099f57634e487b7160e01b85526022600452602485fd5b6080880183905260a088018180156109be57600181146109d4576109ff565b60ff198616825284151560051b820196506109ff565b60008c81526020902060005b868110156109f9578154848201529085019089016109e0565b83019750505b505050505050809250505082606083015295945050505050565b600060208284031215610a2b57600080fd5b5051919050565b80820180821115610a5357634e487b7160e01b600052601160045260246000fd5b9291505056fea26469706673582212202861d3fc4bd9831f3f04e8b5f7b1f4454c061fe9ecb1ecb64c7850ddf1a6bdcb64736f6c6343000810003360a060408190526318f05c0160e11b8152738de6ddbcd5053d32292aaa0d2105a32d108484a6906331e0b8029060a490602090600481865af41580156200004a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000070919062000090565b6001600160a01b03166080523480156200008957600080fd5b50620000c2565b600060208284031215620000a357600080fd5b81516001600160a01b0381168114620000bb57600080fd5b9392505050565b608051615cac620000de60003960006106b90152615cac6000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063614619541461005c5780636e832f07146100665780637284e4161461007a578063bf0fbcec1461008f578063f99e36bc146100b0575b600080fd5b6100646100b8565b005b604051600181526020015b60405180910390f35b610082610193565b60405161007191906158db565b6100a261009d3660046158ee565b6101af565b604051908152602001610071565b610064610259565b738de6ddbcd5053d32292aaa0d2105a32d108484a66335329d4c4260016040516001600160e01b031960e085901b16815264ffffffffff909216600483015215156024820152604401602060405180830381865af415801561011e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101429190615907565b6101895760405162461bcd60e51b81526020600482015260146024820152734f757473696465206f666669636520686f75727360601b604482015260640160405180910390fd5b610191610259565b565b6040518060a00160405280606e8152602001615c09606e913981565b600064ffffffffff8211156101c357600080fd5b6040805163692aba2b60e11b815264ffffffffff808516600483015242166024820152600160448201529051738de6ddbcd5053d32292aaa0d2105a32d108484a69163d25574569160648083019260209291908290030181865af415801561022f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102539190615929565b92915050565b600061027873da0ab1e0017debcd72be8599041a2aa3ba7e740f6108ee565b60408051600180825281830190925291925060009190602080830190803683370190505090507338e4254bd82ed5ee97cd1c4278faae748d998865816000815181106102c6576102c6615958565b6001600160a01b039092166020928302919091018201526040805160c0808201835273929d9a1435662357f54adcf64dcee4d6b867a6f98252734cf3daefa2683cd18df00f7aff5169c00a9eccd58285015273a1ea1ba18e88c381c724a75f23a130420c403f9a8284015273511485bbd96e7e3a056a8d1b84c5071071c52d6f6060808401919091527338e4254bd82ed5ee97cd1c4278faae748d998865608080850191909152845160a0818101875273f9a9cfd3229e985b91f99bc866d42938044ffa1c825273ce01c90de7fd1bcfa39e237fe6d8d9f569e8a6a3828901527335526314f18feb5b7f124e40d6a99d64f7d7e89a8288015273b8f8c7caabfa320717e3e848948450e120f0d9bb9382019390935273473d777f608c3c24b441ab6bd4bbca6b7f9af90b9181019190915290830152825190810190925260058252610688928592908101610426670de0b6b3a7640000638f0d1800615984565b8152602001600a815260200173c2ffbbdccf1466eb8968a846179191cb881ecdff6001600160a01b031681526020016106c08152602001604051806102a001604052806a4c534556322d534b592d4160a81b8152602001878152602001600081526020016d0166bb7f0435c9e717bb45005915602d1b6175306104a99190615984565b81526b033b2e3cf00c157ec6dcd860602082015260400160646104d8676765c793fa10079d601b1b607d615984565b6104e291906159a3565b815260200160646104ff676765c793fa10079d601b1b6078615984565b61050991906159a3565b81526117706020820152604001606461052e676765c793fa10079d601b1b6028615984565b61053891906159a3565b81526020016103e8610553670de0b6b3a76400006001615984565b61055d91906159a3565b815260200161057f6d0166bb7f0435c9e717bb45005915602d1b61012c615984565b81526003602082015260400160646105a0670de0b6b3a76400006071615984565b6105aa91906159a3565b81526020016105cd6d0166bb7f0435c9e717bb45005915602d1b6203d090615984565b81526000602082015260400160646105f1676765c793fa10079d601b1b6063615984565b6105fb91906159a3565b8152603c602082015260016040820152606001600a610626676765c793fa10079d601b1b6005615984565b61063091906159a3565b81526020016040518060400160405280600c81526020016b4c6f636b7374616b65536b7960a01b8152508152602001604051806040016040528060058152602001646c73534b5960d81b8152508152508152506108ff565b6040516336c497bf60e11b81527335526314f18feb5b7f124e40d6a99d64f7d7e89a60048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166024820152738de6ddbcd5053d32292aaa0d2105a32d108484a690636d892f7e9060440160006040518083038186803b15801561071557600080fd5b505af4158015610729573d6000803e3d6000fd5b50506040516319d900a160e01b81526a4d43445f50524f5445474f60a81b6004820152735c9c3cb0490938c9234abdded37a191576ed86246024820152738de6ddbcd5053d32292aaa0d2105a32d108484a692506319d900a1915060440160006040518083038186803b15801561079f57600080fd5b505af41580156107b3573d6000803e3d6000fd5b5050604051635f3a7dd760e01b81526020600482015260066024820152650312e32302e360d41b6044820152738de6ddbcd5053d32292aaa0d2105a32d108484a69250635f3a7dd7915060640160006040518083038186803b15801561081857600080fd5b505af415801561082c573d6000803e3d6000fd5b50506040805160048082526024820183526020820180516001600160e01b0316631851865560e21b1790529151635f30016160e11b8152733300f198988e4c9c63f75df86de36421f06af8c4945063be6002c293506108a29273c40611ac4fff8572dc5f02a238176edcf15ea7ba9291016159c5565b6000604051808303816000875af11580156108c1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108e991908101906159f1565b505050565b6108f6615817565b610253826122f5565b82516040516321f8a72160e01b815262534b5960e81b60048201526000916001600160a01b0316906321f8a72190602401602060405180830381865afa15801561094d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109719190615a9e565b9050806001600160a01b031683600001516001600160a01b03166312d43a516040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e39190615a9e565b6001600160a01b0316146109f657600080fd5b816000015183600001516001600160a01b031663b404edbc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a619190615929565b14610a6b57600080fd5b816020015183600001516001600160a01b031663f8b17a156040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ab2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad69190615929565b14610ae057600080fd5b816040015183600001516001600160a01b0316637189cae86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4b9190615929565b14610b5557600080fd5b82600001516001600160a01b031683602001516001600160a01b031663ffd864d36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ba5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc99190615a9e565b6001600160a01b031614610bdc57600080fd5b83516040516321f8a72160e01b815274564f54455f44454c45474154455f464143544f525960581b60048201526001600160a01b03909116906321f8a72190602401602060405180830381865afa158015610c3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5f9190615a9e565b6001600160a01b031663547174966040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc09190615a9e565b6001600160a01b031683602001516001600160a01b031663547174966040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2f9190615a9e565b6001600160a01b031614610d4257600080fd5b81606001516001600160a01b031683606001516001600160a01b0316632e7dc6af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db69190615a9e565b6001600160a01b031614610dc957600080fd5b8260a00151600001516001600160a01b031683608001516001600160a01b03166372f702f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e419190615a9e565b6001600160a01b031614610e5457600080fd5b83516040516321f8a72160e01b8152635553445360e01b60048201526001600160a01b03909116906321f8a72190602401602060405180830381865afa158015610ea2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ec69190615a9e565b6001600160a01b031683608001516001600160a01b031663d1af0c7d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f359190615a9e565b6001600160a01b031614610f4857600080fd5b83516040516321f8a72160e01b8152684d43445f504155534560b81b60048201526001600160a01b03909116906321f8a72190602401602060405180830381865afa158015610f9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fbf9190615a9e565b8351604051637a9e5e4b60e01b81526001600160a01b039182166004820152911690637a9e5e4b90602401600060405180830381600087803b15801561100457600080fd5b505af1158015611018573d6000803e3d6000fd5b505085516040516321f8a72160e01b81526b53504c49545445525f4d4f4d60a01b60048201526001600160a01b0390911692506321f8a7219150602401602060405180830381865afa158015611072573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110969190615a9e565b8351604051637a9e5e4b60e01b81526001600160a01b039182166004820152911690637a9e5e4b90602401600060405180830381600087803b1580156110db57600080fd5b505af11580156110ef573d6000803e3d6000fd5b505085516040516321f8a72160e01b8152664f534d5f4d4f4d60c81b60048201526001600160a01b0390911692506321f8a7219150602401602060405180830381865afa158015611144573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111689190615a9e565b8351604051637a9e5e4b60e01b81526001600160a01b039182166004820152911690637a9e5e4b90602401600060405180830381600087803b1580156111ad57600080fd5b505af11580156111c1573d6000803e3d6000fd5b505085516040516321f8a72160e01b81526a434c49505045525f4d4f4d60a81b60048201526001600160a01b0390911692506321f8a7219150602401602060405180830381865afa15801561121a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123e9190615a9e565b8351604051637a9e5e4b60e01b81526001600160a01b039182166004820152911690637a9e5e4b90602401600060405180830381600087803b15801561128357600080fd5b505af1158015611297573d6000803e3d6000fd5b505085516040516321f8a72160e01b8152694449524543545f4d4f4d60b01b60048201526001600160a01b0390911692506321f8a7219150602401602060405180830381865afa1580156112ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113139190615a9e565b8351604051637a9e5e4b60e01b81526001600160a01b039182166004820152911690637a9e5e4b90602401600060405180830381600087803b15801561135857600080fd5b505af115801561136c573d6000803e3d6000fd5b505085516040516321f8a72160e01b815272535441524b4e45545f455343524f575f4d4f4d60681b60048201526001600160a01b0390911692506321f8a7219150602401602060405180830381865afa1580156113cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f19190615a9e565b8351604051637a9e5e4b60e01b81526001600160a01b039182166004820152911690637a9e5e4b90602401600060405180830381600087803b15801561143657600080fd5b505af115801561144a573d6000803e3d6000fd5b505085516040516321f8a72160e01b8152674c494e455f4d4f4d60c01b60048201526001600160a01b0390911692506321f8a7219150602401602060405180830381865afa1580156114a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c49190615a9e565b8351604051637a9e5e4b60e01b81526001600160a01b039182166004820152911690637a9e5e4b90602401600060405180830381600087803b15801561150957600080fd5b505af115801561151d573d6000803e3d6000fd5b505085516040516321f8a72160e01b81526b4c4954455f50534d5f4d4f4d60a01b60048201526001600160a01b0390911692506321f8a7219150602401602060405180830381865afa158015611577573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159b9190615a9e565b8351604051637a9e5e4b60e01b81526001600160a01b039182166004820152911690637a9e5e4b90602401600060405180830381600087803b1580156115e057600080fd5b505af11580156115f4573d6000803e3d6000fd5b505085516040516321f8a72160e01b81526953504245414d5f4d4f4d60b01b60048201526001600160a01b0390911692506321f8a7219150602401602060405180830381865afa15801561164c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116709190615a9e565b8351604051637a9e5e4b60e01b81526001600160a01b039182166004820152911690637a9e5e4b90602401600060405180830381600087803b1580156116b557600080fd5b505af11580156116c9573d6000803e3d6000fd5b50508551855160405163ca446dd960e01b8152664d43445f41444d60c81b60048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b15801561172457600080fd5b505af1158015611738573d6000803e3d6000fd5b505085516040516321f8a72160e01b815274564f54455f44454c45474154455f464143544f525960581b60048201526001600160a01b03909116925063ca446dd9915082906321f8a72190602401602060405180830381865afa1580156117a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c79190615a9e565b6040516001600160e01b031960e084901b1681527f564f54455f44454c45474154455f464143544f52595f4c45474143590000000060048201526001600160a01b039091166024820152604401600060405180830381600087803b15801561182e57600080fd5b505af1158015611842573d6000803e3d6000fd5b50508551602086015160405163ca446dd960e01b815274564f54455f44454c45474154455f464143544f525960581b60048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b1580156118ae57600080fd5b505af11580156118c2573d6000803e3d6000fd5b505050506118d48484604001516124d7565b83516040516321f8a72160e01b81526704d43445f464c41560c41b60048201526001600160a01b03909116906321f8a72190602401602060405180830381865afa158015611926573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194a9190615a9e565b606083015160405163d4e8be8360e01b81526207069760ec1b60048201526001600160a01b03918216602482015291169063d4e8be8390604401600060405180830381600087803b15801561199e57600080fd5b505af11580156119b2573d6000803e3d6000fd5b50508551606085015160405163ca446dd960e01b81526e464c41505f534b595f4f5241434c4560881b60048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b158015611a1857600080fd5b505af1158015611a2c573d6000803e3d6000fd5b50508551606086015160405163ca446dd960e01b8152665049505f534b5960c81b60048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b158015611a8a57600080fd5b505af1158015611a9e573d6000803e3d6000fd5b505085516040516321f8a72160e01b8152681350d117d4d413125560ba1b6004820152600093506001600160a01b0390911691506321f8a72190602401602060405180830381865afa158015611af8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b1c9190615a9e565b9050611b4384608001516040518060200160405280846001600160a01b0316815250612a71565b83608001516001600160a01b031663cc1a378f84608001516040518263ffffffff1660e01b8152600401611b7991815260200190565b600060405180830381600087803b158015611b9357600080fd5b505af1158015611ba7573d6000803e3d6000fd5b50505050608084015160405163d4e8be8360e01b8152636661726d60e01b60048201526001600160a01b0391821660248201529082169063d4e8be8390604401600060405180830381600087803b158015611c0157600080fd5b505af1158015611c15573d6000803e3d6000fd5b50508651608087015160405163ca446dd960e01b815271524557415244535f4c53534b595f5553445360701b60048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b158015611c7e57600080fd5b505af1158015611c92573d6000803e3d6000fd5b505086516040516321f8a72160e01b815271524557415244535f4c534d4b525f5553445360701b60048201526001600160a01b03909116925063ca446dd9915082906321f8a72190602401602060405180830381865afa158015611cfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1e9190615a9e565b6040516001600160e01b031960e084901b1681527f524557415244535f4c534d4b525f555344535f4c45474143590000000000000060048201526001600160a01b039091166024820152604401600060405180830381600087803b158015611d8557600080fd5b505af1158015611d99573d6000803e3d6000fd5b50508651604051634fd7b7db60e11b815271524557415244535f4c534d4b525f5553445360701b60048201526001600160a01b039091169250639faf6fb69150602401600060405180830381600087803b158015611df657600080fd5b505af1158015611e0a573d6000803e3d6000fd5b50505050611e21858560a001518560a00151612ad3565b84516040516321f8a72160e01b8152664d43445f564f5760c81b60048201526001600160a01b03909116906321f8a72190602401602060405180830381865afa158015611e72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e969190615a9e565b604051630a6ba04560e21b815263073756d760e41b600482015260001960248201526001600160a01b0391909116906329ae811490604401600060405180830381600087803b158015611ee857600080fd5b505af1158015611efc573d6000803e3d6000fd5b505086516040516321f8a72160e01b8152664d43445f45534d60c81b60048201526001600160a01b0390911692506321f8a7219150602401602060405180830381865afa158015611f51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f759190615a9e565b604051630a6ba04560e21b81526236b4b760e91b600482015260001960248201526001600160a01b0391909116906329ae811490604401600060405180830381600087803b158015611fc657600080fd5b505af1158015611fda573d6000803e3d6000fd5b505086516040516321f8a72160e01b81526626a1a22fa3a7ab60c91b60048201526001600160a01b03909116925063ca446dd9915082906321f8a72190602401602060405180830381865afa158015612037573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061205b9190615a9e565b6040516001600160e01b031960e084901b1681526226a5a960e91b60048201526001600160a01b039091166024820152604401600060405180830381600087803b1580156120a857600080fd5b505af11580156120bc573d6000803e3d6000fd5b5050865160405163ca446dd960e01b81526626a1a22fa3a7ab60c91b60048201526001600160a01b038681166024830152909116925063ca446dd99150604401600060405180830381600087803b15801561211657600080fd5b505af115801561212a573d6000803e3d6000fd5b50508651604051634fd7b7db60e11b81526e4d43445f474f565f414354494f4e5360881b60048201526001600160a01b039091169250639faf6fb69150602401600060405180830381600087803b15801561218457600080fd5b505af1158015612198573d6000803e3d6000fd5b505086516040516321f8a72160e01b81526811d3d597d1d550549160ba1b60048201526001600160a01b03909116925063ca446dd9915082906321f8a72190602401602060405180830381865afa1580156121f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221b9190615a9e565b6040516001600160e01b031960e084901b168152681352d497d1d550549160ba1b60048201526001600160a01b039091166024820152604401600060405180830381600087803b15801561226e57600080fd5b505af1158015612282573d6000803e3d6000fd5b50508651604051634fd7b7db60e11b81526811d3d597d1d550549160ba1b60048201526001600160a01b039091169250639faf6fb69150602401600060405180830381600087803b1580156122d657600080fd5b505af11580156122ea573d6000803e3d6000fd5b505050505050505050565b6122fd615817565b6001600160a01b038216815261231d81661350d117d5905560ca1b61579f565b6001600160a01b03166020820152612344816b4d43445f4a4f494e5f44414960a01b61579f565b6001600160a01b0316604082015261236681664d43445f44414960c81b61579f565b6001600160a01b0316606082015261238881664d43445f564f5760c81b61579f565b6001600160a01b031660808201526123aa81664d43445f444f4760c81b61579f565b6001600160a01b031660a08201526123cc81661350d117d413d560ca1b61579f565b6001600160a01b031660c08201526123ee81664d43445f4a554760c81b61579f565b6001600160a01b031660e082015261241181671350d117d4d413d560c21b61579f565b6001600160a01b031661010082015261243481661350d117d1539160ca1b61579f565b6001600160a01b031661012082015261245881674d43445f4355524560c01b61579f565b6001600160a01b031661014082015261247c816704d43445f464c41560c41b61579f565b6001600160a01b03166101608201526124a0816704d43445f464c4f560c41b61579f565b6001600160a01b03166101808201526124c381664d43445f45534d60c81b61579f565b6001600160a01b03166101a0820152919050565b81516040516321f8a72160e01b8152664d4b525f534b5960c81b60048201526000916001600160a01b0316906321f8a72190602401602060405180830381865afa158015612529573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254d9190615a9e565b90506000816001600160a01b0316637e992cb86040518163ffffffff1660e01b8152600401602060405180830381865afa15801561258f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b39190615a9e565b90506000826001600160a01b031663692318046040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126199190615a9e565b90506000836001600160a01b0316632c4e722e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561265b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061267f9190615929565b9050826001600160a01b0316856001600160a01b0316637e992cb86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ed9190615a9e565b6001600160a01b03161461270057600080fd5b816001600160a01b0316856001600160a01b031663692318046040518163ffffffff1660e01b8152600401602060405180830381865afa158015612748573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061276c9190615a9e565b6001600160a01b03161461277f57600080fd5b80856001600160a01b0316632c4e722e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127e29190615929565b146127ec57600080fd5b826001600160a01b031663bf7e214f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561282a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284e9190615a9e565b604051639c52a7f160e01b81526001600160a01b0386811660048301529190911690639c52a7f190602401600060405180830381600087803b15801561289357600080fd5b505af11580156128a7573d6000803e3d6000fd5b50505050816001600160a01b03166340c10f198683866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061291e9190615929565b6129289190615984565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561296e57600080fd5b505af1158015612982573d6000803e3d6000fd5b5050875160405163ca446dd960e01b81526d4d4b525f534b595f4c454741435960901b60048201526001600160a01b038881166024830152909116925063ca446dd99150604401600060405180830381600087803b1580156129e357600080fd5b505af11580156129f7573d6000803e3d6000fd5b5050875160405163ca446dd960e01b8152664d4b525f534b5960c81b60048201526001600160a01b038981166024830152909116925063ca446dd99150604401600060405180830381600087803b158015612a5157600080fd5b505af1158015612a65573d6000803e3d6000fd5b50505050505050505050565b8051604051631976214360e01b81526001600160a01b03918216600482015290831690631976214390602401600060405180830381600087803b158015612ab757600080fd5b505af1158015612acb573d6000803e3d6000fd5b505050505050565b604080516101008101825283516001600160a01b03908116825260208086015182169083015284830151811682840152606080860151821690830152608080860151821690830152855192516321f8a72160e01b81526f4c4f434b5354414b455f454e47494e4560801b600482015260009360a084019216906321f8a72190602401602060405180830381865afa158015612b72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b969190615a9e565b6001600160a01b03908116825286516040516321f8a72160e01b8152704d43445f49414d5f4155544f5f4c494e4560781b60048201526020909301929116906321f8a72190602401602060405180830381865afa158015612bfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c1f9190615a9e565b6001600160a01b03908116825286516040516321f8a72160e01b815262534b5960e81b60048201526020909301929116906321f8a72190602401602060405180830381865afa158015612c76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c9a9190615a9e565b6001600160a01b0316815250905060008160a001516001600160a01b031663c5ce281e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d109190615929565b83519091508103612d2057600080fd5b84516040516321f8a72160e01b815274564f54455f44454c45474154455f464143544f525960581b60048201526001600160a01b03909116906321f8a72190602401602060405180830381865afa158015612d7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da39190615a9e565b6001600160a01b031682602001516001600160a01b0316631b7a353e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612dee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e129190615a9e565b6001600160a01b031614612e2557600080fd5b84602001516001600160a01b031682602001516001600160a01b03166336569e776040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e999190615a9e565b6001600160a01b031614612eac57600080fd5b84516040516321f8a72160e01b8152682aa9a229afa527a4a760b91b60048201526001600160a01b03909116906321f8a72190602401602060405180830381865afa158015612eff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f239190615a9e565b6001600160a01b031682602001516001600160a01b031663fa1e2e866040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f929190615a9e565b6001600160a01b031614612fa557600080fd5b84516040516321f8a72160e01b8152635553445360e01b60048201526001600160a01b03909116906321f8a72190602401602060405180830381865afa158015612ff3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130179190615a9e565b6001600160a01b031682602001516001600160a01b0316634cf282fb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613062573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130869190615a9e565b6001600160a01b03161461309957600080fd5b826000015182602001516001600160a01b031663c5ce281e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131049190615929565b1461310e57600080fd5b8160e001516001600160a01b031682602001516001600160a01b031663692318046040518163ffffffff1660e01b8152600401602060405180830381865afa15801561315e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131829190615a9e565b6001600160a01b03161461319557600080fd5b81600001516001600160a01b031682602001516001600160a01b0316636a6e9edf6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156131e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132099190615a9e565b6001600160a01b03161461321c57600080fd5b826040015182602001516001600160a01b031663ddca3f436040518163ffffffff1660e01b8152600401602060405180830381865afa158015613263573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132879190615929565b1461329157600080fd5b826000015182604001516001600160a01b031663c5ce281e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132fc9190615929565b1461330657600080fd5b84602001516001600160a01b031682604001516001600160a01b03166336569e776040518163ffffffff1660e01b8152600401602060405180830381865afa158015613356573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061337a9190615a9e565b6001600160a01b03161461338d57600080fd5b81602001516001600160a01b031682604001516001600160a01b031663c9d4623f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156133dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134019190615a9e565b6001600160a01b03161461341457600080fd5b8460a001516001600160a01b031682604001516001600160a01b031663c3b3ad7f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613464573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134889190615a9e565b6001600160a01b03161461349b57600080fd5b8461010001516001600160a01b031682604001516001600160a01b0316632e77468d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135109190615a9e565b6001600160a01b03161461352357600080fd5b8160a001516001600160a01b031682608001516001600160a01b031663e0d680a66040518163ffffffff1660e01b8152600401602060405180830381865afa158015613573573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135979190615a9e565b6001600160a01b0316146135aa57600080fd5b81602001516001600160a01b031682608001516001600160a01b031663339f7f536040518163ffffffff1660e01b8152600401602060405180830381865afa1580156135fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061361e9190615a9e565b6001600160a01b03161461363157600080fd5b84516040516321f8a72160e01b8152664d4b525f534b5960c81b60048201526001600160a01b03909116906321f8a72190602401602060405180830381865afa158015613682573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136a69190615a9e565b6001600160a01b031682608001516001600160a01b03166315cd07b66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156136f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137159190615a9e565b6001600160a01b03161461372857600080fd5b84516040516321f8a72160e01b81526809a8688be8c9882a6960bb1b60048201526001600160a01b03909116906321f8a72190602401602060405180830381865afa15801561377b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061379f9190615a9e565b6001600160a01b031682608001516001600160a01b031663d336c82d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061380e9190615a9e565b6001600160a01b03161461382157600080fd5b60208501518351604051636cb1c69b60e11b815260048101919091526000916001600160a01b03169063d9638d369060240160a060405180830381865afa158015613870573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138949190615ac7565b509350505050806000146138a757600080fd5b60c08301518451604051636cb1c69b60e11b81526001600160a01b039092169163d9638d36916138dd9160040190815260200190565b60a0604051808303816000875af11580156138fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139209190615b22565b509293505082159150613934905057600080fd5b836101a001518460600151111561394a57600080fd5b676765c793fa10079d601b1b84608001511015801561397957506b033b2e3dd0d78f60556d6583846080015111155b61398257600080fd5b676765c793fa10079d601b1b8460a00151101580156139b957506139b2676765c793fa10079d601b1b600a615984565b8460a00151105b6139c257600080fd5b676765c793fa10079d601b1b8460c00151101580156139f957506139f2676765c793fa10079d601b1b600a615984565b8460c00151105b613a0257600080fd5b676765c793fa10079d601b1b84610100015110613a1e57600080fd5b670de0b6b3a764000084610120015110613a3757600080fd5b613a546d0166bb7f0435c9e717bb45005915602d1b6103e8615984565b8461014001511115613a6557600080fd5b670de0b6b3a764000084610180015110158015613a985750613a90670de0b6b3a76400006002615984565b846101800151105b613aa157600080fd5b676765c793fa10079d601b1b84610240015110613abd57600080fd5b60a083015160808401516040516332fd71af60e11b81526001600160a01b0391821660048201529116906365fae35e90602401600060405180830381600087803b158015613b0a57600080fd5b505af1158015613b1e573d6000803e3d6000fd5b5050506020870151604051630d05943f60e11b815260048101859052636c696e6560e01b6024820152600060448201526001600160a01b039091169150631a0b287e90606401600060405180830381600087803b158015613b7e57600080fd5b505af1158015613b92573d6000803e3d6000fd5b50505060c084015160405163c465f07760e01b8152600481018590526001600160a01b03909116915063c465f07790602401600060405180830381600087803b158015613bde57600080fd5b505af1158015613bf2573d6000803e3d6000fd5b5050505060208601518451604051633b66319560e01b815260048101919091526001600160a01b0390911690633b66319590602401600060405180830381600087803b158015613c4157600080fd5b505af1158015613c55573d6000803e3d6000fd5b50505050602086015184516060860151604051630d05943f60e11b8152600481019290925263191d5cdd60e21b602483015260448201526001600160a01b0390911690631a0b287e90606401600060405180830381600087803b158015613cbb57600080fd5b505af1158015613ccf573d6000803e3d6000fd5b505050602080880151908501516040516332fd71af60e11b81526001600160a01b039182166004820152911691506365fae35e90602401600060405180830381600087803b158015613d2057600080fd5b505af1158015613d34573d6000803e3d6000fd5b505050602087015160408086015190516332fd71af60e11b81526001600160a01b039182166004820152911691506365fae35e90602401600060405180830381600087803b158015613d8557600080fd5b505af1158015613d99573d6000803e3d6000fd5b505050602087015160808501516040516332fd71af60e11b81526001600160a01b039182166004820152911691506365fae35e90602401600060405180830381600087803b158015613dea57600080fd5b505af1158015613dfe573d6000803e3d6000fd5b5050505060e08601518451604051633b66319560e01b815260048101919091526001600160a01b0390911690633b66319590602401600060405180830381600087803b158015613e4d57600080fd5b505af1158015613e61573d6000803e3d6000fd5b5050505060e086015184516080860151604051630d05943f60e11b81526004810192909252636475747960e01b602483015260448201526001600160a01b0390911690631a0b287e90606401600060405180830381600087803b158015613ec757600080fd5b505af1158015613edb573d6000803e3d6000fd5b505087516040516321f8a72160e01b8152665049505f534b5960c81b6004820152600093506001600160a01b0390911691506321f8a72190602401602060405180830381865afa158015613f33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f579190615a9e565b87516040516321f8a72160e01b81526a434c49505045525f4d4f4d60a81b60048201529192506000916001600160a01b03909116906321f8a72190602401602060405180830381865afa158015613fb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fd69190615a9e565b610100890151604051633ca70a7160e21b81526001600160a01b03918216600482015291925083169063f29c29c490602401600060405180830381600087803b15801561402257600080fd5b505af1158015614036573d6000803e3d6000fd5b505050506040858101519051633ca70a7160e21b81526001600160a01b0391821660048201529083169063f29c29c490602401600060405180830381600087803b15801561408357600080fd5b505af1158015614097573d6000803e3d6000fd5b5050604051633ca70a7160e21b81526001600160a01b0384811660048301528516925063f29c29c49150602401600060405180830381600087803b1580156140de57600080fd5b505af11580156140f2573d6000803e3d6000fd5b50505050610120880151604051633ca70a7160e21b81526001600160a01b0391821660048201529083169063f29c29c490602401600060405180830381600087803b15801561414057600080fd5b505af1158015614154573d6000803e3d6000fd5b505089516040516321f8a72160e01b8152664f534d5f4d4f4d60c81b6004820152600093506001600160a01b0390911691506321f8a72190602401602060405180830381865afa1580156141ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141d09190615a9e565b6040516332fd71af60e11b81526001600160a01b038083166004830152919250908416906365fae35e90602401600060405180830381600087803b15801561421757600080fd5b505af115801561422b573d6000803e3d6000fd5b505088516040516364c66fc360e11b815260048101919091526001600160a01b0386811660248301528416925063c98cdf869150604401600060405180830381600087803b15801561427c57600080fd5b505af1158015614290573d6000803e3d6000fd5b5050506101008a0151885160a08a0151604051630d05943f60e11b81526001600160a01b039093169450631a0b287e93506142e292600401918252621b585d60ea1b6020830152604082015260600190565b600060405180830381600087803b1580156142fc57600080fd5b505af1158015614310573d6000803e3d6000fd5b50505050610100880151865160405163ebecb39d60e01b815260048101919091526207069760ec1b60248201526001600160a01b0384811660448301529091169063ebecb39d90606401600060405180830381600087803b15801561437457600080fd5b505af1158015614388573d6000803e3d6000fd5b505050506101008801518651604051631504460f60e01b815260048101919091526001600160a01b0390911690631504460f90602401600060405180830381600087803b1580156143d857600080fd5b505af11580156143ec573d6000803e3d6000fd5b5050505060a08801518651604087810151905163ebecb39d60e01b81526004810192909252630636c69760e41b60248301526001600160a01b0390811660448301529091169063ebecb39d90606401600060405180830381600087803b15801561445557600080fd5b505af1158015614469573d6000803e3d6000fd5b5050505060a08801518651610180880151604051630d05943f60e11b8152600481019290925263063686f760e41b602483015260448201526001600160a01b0390911690631a0b287e90606401600060405180830381600087803b1580156144d057600080fd5b505af11580156144e4573d6000803e3d6000fd5b5050505060a088015186516101a0880151604051630d05943f60e11b8152600481019290925263686f6c6560e01b602483015260448201526001600160a01b0390911690631a0b287e90606401600060405180830381600087803b15801561454b57600080fd5b505af115801561455f573d6000803e3d6000fd5b50505060a089015160408088015190516332fd71af60e11b81526001600160a01b039182166004820152911691506365fae35e90602401600060405180830381600087803b1580156145b057600080fd5b505af11580156145c4573d6000803e3d6000fd5b5050865160208801516040516332fd71af60e11b81526001600160a01b039182166004820152911692506365fae35e9150602401600060405180830381600087803b15801561461257600080fd5b505af1158015614626573d6000803e3d6000fd5b505050602086015160e08a015160405163d4e8be8360e01b8152626a756760e81b60048201526001600160a01b0391821660248201529116915063d4e8be8390604401600060405180830381600087803b15801561468357600080fd5b505af1158015614697573d6000803e3d6000fd5b5050505060005b8660200151518110156147ec5787600001516001600160a01b0316876020015182815181106146cf576146cf615958565b60200260200101516001600160a01b03166372f702f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015614714573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147389190615a9e565b6001600160a01b03161461474b57600080fd5b85602001516001600160a01b031663aff7b07d8860200151838151811061477457614774615958565b60200260200101516040518263ffffffff1660e01b81526004016147a791906001600160a01b0391909116815260200190565b600060405180830381600087803b1580156147c157600080fd5b505af11580156147d5573d6000803e3d6000fd5b5050505080806147e490615b79565b91505061469e565b50602085015160408087015190516332fd71af60e11b81526001600160a01b0391821660048201529116906365fae35e90602401600060405180830381600087803b15801561483a57600080fd5b505af115801561484e573d6000803e3d6000fd5b50505060408087015160c08901519151630a6ba04560e21b815262313ab360e91b600482015260248101929092526001600160a01b031691506329ae811490604401600060405180830381600087803b1580156148aa57600080fd5b505af11580156148be573d6000803e3d6000fd5b50505060408087015160e08901519151630a6ba04560e21b8152631d185a5b60e21b600482015260248101929092526001600160a01b031691506329ae811490604401600060405180830381600087803b15801561491b57600080fd5b505af115801561492f573d6000803e3d6000fd5b5050506040808701516101008901519151630a6ba04560e21b8152630637573760e41b600482015260248101929092526001600160a01b031691506329ae811490604401600060405180830381600087803b15801561498d57600080fd5b505af11580156149a1573d6000803e3d6000fd5b5050506040808701516101208901519151630a6ba04560e21b8152630636869760e41b600482015260248101929092526001600160a01b031691506329ae811490604401600060405180830381600087803b1580156149ff57600080fd5b505af1158015614a13573d6000803e3d6000fd5b5050506040808701516101408901519151630a6ba04560e21b81526207469760ec1b600482015260248101929092526001600160a01b031691506329ae811490604401600060405180830381600087803b158015614a7057600080fd5b505af1158015614a84573d6000803e3d6000fd5b5050506040808701516101608901519151630a6ba04560e21b8152661cdd1bdc1c195960ca1b600482015260248101929092526001600160a01b031691506329ae811490604401600060405180830381600087803b158015614ae557600080fd5b505af1158015614af9573d6000803e3d6000fd5b50505060408087015160808b0151915163d4e8be8360e01b815262766f7760e81b60048201526001600160a01b0392831660248201529116915063d4e8be8390604401600060405180830381600087803b158015614b5657600080fd5b505af1158015614b6a573d6000803e3d6000fd5b5050506040808701516060880151915163d4e8be8360e01b81526363616c6360e01b60048201526001600160a01b0392831660248201529116915063d4e8be8390604401600060405180830381600087803b158015614bc857600080fd5b505af1158015614bdc573d6000803e3d6000fd5b5050505084604001516001600160a01b0316630cbb58626040518163ffffffff1660e01b8152600401600060405180830381600087803b158015614c1f57600080fd5b505af1158015614c33573d6000803e3d6000fd5b50505060408087015160a08b015191516332fd71af60e11b81526001600160a01b039283166004820152911691506365fae35e90602401600060405180830381600087803b158015614c8457600080fd5b505af1158015614c98573d6000803e3d6000fd5b5050506040808701516101208b015191516332fd71af60e11b81526001600160a01b039283166004820152911691506365fae35e90602401600060405180830381600087803b158015614cea57600080fd5b505af1158015614cfe573d6000803e3d6000fd5b50505060408087015190516332fd71af60e11b81526001600160a01b03848116600483015290911691506365fae35e90602401600060405180830381600087803b158015614d4b57600080fd5b505af1158015614d5f573d6000803e3d6000fd5b505050506101c086015115614de25760608501516101c0870151604051630a6ba04560e21b81526274617560e81b600482015260248101919091526001600160a01b03909116906329ae811490604401600060405180830381600087803b158015614dc957600080fd5b505af1158015614ddd573d6000803e3d6000fd5b505050505b6101e086015115614e615760608501516101e0870151604051630a6ba04560e21b81526218dd5d60ea1b600482015260248101919091526001600160a01b03909116906329ae811490604401600060405180830381600087803b158015614e4857600080fd5b505af1158015614e5c573d6000803e3d6000fd5b505050505b61020086015115614ee1576060850151610200870151604051630a6ba04560e21b8152630737465760e41b600482015260248101919091526001600160a01b03909116906329ae811490604401600060405180830381600087803b158015614ec857600080fd5b505af1158015614edc573d6000803e3d6000fd5b505050505b85610220015115614fc75787516040516321f8a72160e01b8152674c494e455f4d4f4d60c01b60048201526001600160a01b03909116906321f8a72190602401602060405180830381865afa158015614f3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f629190615a9e565b865160405163796e9cc960e11b81526001600160a01b03929092169163f2dd399291614f949160040190815260200190565b600060405180830381600087803b158015614fae57600080fd5b505af1158015614fc2573d6000803e3d6000fd5b505050505b610240860151156150415760408086015161024088015191516317f21e8360e31b81526001600160a01b039182166004820152602481019290925282169063bf90f41890604401600060405180830381600087803b15801561502857600080fd5b505af115801561503c573d6000803e3d6000fd5b505050505b87516040516321f8a72160e01b81526b494c4b5f524547495354525960a01b60048201526001600160a01b03909116906321f8a72190602401602060405180830381865afa158015615097573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150bb9190615a9e565b6001600160a01b0316634d8835e6876000015160008860e0015160126007888c604001518e61026001518f61028001516040518a63ffffffff1660e01b815260040161510f99989796959493929190615b92565b600060405180830381600087803b15801561512957600080fd5b505af115801561513d573d6000803e3d6000fd5b505089516040516321f8a72160e01b81526c2627a1a5a9aa20a5a2afa6a5a960991b60048201526001600160a01b03909116925063ca446dd9915082906321f8a72190602401602060405180830381865afa1580156151a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906151c49190615a9e565b6040516001600160e01b031960e084901b168152734c4f434b5354414b455f4d4b525f4f4c445f563160601b60048201526001600160a01b039091166024820152604401600060405180830381600087803b15801561522257600080fd5b505af1158015615236573d6000803e3d6000fd5b5050895160a088015160405163ca446dd960e01b81527f4c4f434b5354414b455f454e47494e455f4f4c445f563100000000000000000060048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b1580156152aa57600080fd5b505af11580156152be573d6000803e3d6000fd5b505089516040516321f8a72160e01b81526d04c4f434b5354414b455f434c49560941b60048201526001600160a01b03909116925063ca446dd9915082906321f8a72190602401602060405180830381865afa158015615322573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906153469190615a9e565b6040516001600160e01b031960e084901b168152744c4f434b5354414b455f434c49505f4f4c445f563160581b60048201526001600160a01b039091166024820152604401600060405180830381600087803b1580156153a557600080fd5b505af11580156153b9573d6000803e3d6000fd5b505089516040516321f8a72160e01b8152724c4f434b5354414b455f434c49505f43414c4360681b60048201526001600160a01b03909116925063ca446dd9915082906321f8a72190602401602060405180830381865afa158015615422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906154469190615a9e565b6040516001600160e01b031960e084901b1681527f4c4f434b5354414b455f434c49505f43414c435f4f4c445f563100000000000060048201526001600160a01b039091166024820152604401600060405180830381600087803b1580156154ad57600080fd5b505af11580156154c1573d6000803e3d6000fd5b50508951604051634fd7b7db60e11b81526c2627a1a5a9aa20a5a2afa6a5a960991b60048201526001600160a01b039091169250639faf6fb69150602401600060405180830381600087803b15801561551957600080fd5b505af115801561552d573d6000803e3d6000fd5b50508951875160405163ca446dd960e01b81526c4c4f434b5354414b455f534b5960981b60048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b15801561558e57600080fd5b505af11580156155a2573d6000803e3d6000fd5b50508951602088015160405163ca446dd960e01b81526f4c4f434b5354414b455f454e47494e4560801b60048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b15801561560957600080fd5b505af115801561561d573d6000803e3d6000fd5b50508951604088810151905163ca446dd960e01b81526d04c4f434b5354414b455f434c49560941b60048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b15801561568257600080fd5b505af1158015615696573d6000803e3d6000fd5b50508951606088015160405163ca446dd960e01b8152724c4f434b5354414b455f434c49505f43414c4360681b60048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b15801561570057600080fd5b505af1158015615714573d6000803e3d6000fd5b50508951608088015160405163ca446dd960e01b8152712627a1a5a9aa20a5a2afa6a4a3a920aa27a960711b60048201526001600160a01b0391821660248201529116925063ca446dd99150604401600060405180830381600087803b15801561577d57600080fd5b505af1158015615791573d6000803e3d6000fd5b505050505050505050505050565b81516040516321f8a72160e01b8152600481018390526000916001600160a01b0316906321f8a72190602401602060405180830381865afa925050508015615804575060408051601f3d908101601f1916820190925261580191810190615a9e565b60015b61581057506000610253565b9392505050565b604080516101c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081019190915290565b60005b838110156158a657818101518382015260200161588e565b50506000910152565b600081518084526158c781602086016020860161588b565b601f01601f19169290920160200192915050565b60208152600061581060208301846158af565b60006020828403121561590057600080fd5b5035919050565b60006020828403121561591957600080fd5b8151801515811461581057600080fd5b60006020828403121561593b57600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561599e5761599e61596e565b500290565b6000826159c057634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b03831681526040602082018190526000906159e9908301846158af565b949350505050565b600060208284031215615a0357600080fd5b815167ffffffffffffffff80821115615a1b57600080fd5b818401915084601f830112615a2f57600080fd5b815181811115615a4157615a41615942565b604051601f8201601f19908116603f01168101908382118183101715615a6957615a69615942565b81604052828152876020848701011115615a8257600080fd5b615a9383602083016020880161588b565b979650505050505050565b600060208284031215615ab057600080fd5b81516001600160a01b038116811461581057600080fd5b600080600080600060a08688031215615adf57600080fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b805165ffffffffffff81168114615b1d57600080fd5b919050565b600080600080600060a08688031215615b3a57600080fd5b8551945060208601519350615b5160408701615b07565b9250615b5f60608701615b07565b9150615b6d60808701615b07565b90509295509295909350565b600060018201615b8b57615b8b61596e565b5060010190565b8981526001600160a01b0389811660208301528881166040830152606082018890526080820187905285811660a0830152841660c082015261012060e08201819052600090615be3838201866158af565b9050828103610100840152615bf881856158af565b9c9b50505050505050505050505056fe323032352d30352d3135204d616b657244414f20457865637574697665205370656c6c207c20486173683a20307835396432646430396339356665353235303637613738653164663737666463393564616661346461346339633165356464316137383361663162623838653638a2646970667358221220234a2553e3cbd50b2a06663479a8d564d6dfe5e0f2dd9cd5a44d54a5cc4b731d64736f6c63430008100033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100ce5760003560e01c80637284e4161161008c578063ae8421e111610066578063ae8421e1146101f8578063b0604a2614610205578063f7992d851461020d578063fe7d47bb1461021657600080fd5b80637284e416146101bf5780638456cb59146101c757806396d373e5146101ee57600080fd5b8062a7029b146100d35780630a7a1c4d146100f15780634665096d1461013057806351973ec91461016557806351f91066146101805780636e832f07146101a7575b600080fd5b6100db61021e565b6040516100e891906107f9565b60405180910390f35b6101187f000000000000000000000000c290bf292900318eadade782a1f6953f6e13a33181565b6040516001600160a01b0390911681526020016100e8565b6101577f00000000000000000000000000000000000000000000000000000000684da7a781565b6040519081526020016100e8565b61011873da0ab1e0017debcd72be8599041a2aa3ba7e740f81565b6101577f114a94e507624e00030973aa2e7c5d8f912a92d65868434d704260495c2b3ef881565b6101af6102ac565b60405190151581526020016100e8565b6100db610335565b6101187f000000000000000000000000be286431454714f511008713973d3b053a2d38f381565b6101f66103bd565b005b6002546101af9060ff1681565b6101f66104f7565b61015760005481565b61015761071b565b6001805461022b90610813565b80601f016020809104026020016040519081016040528092919081815260200182805461025790610813565b80156102a45780601f10610279576101008083540402835291602001916102a4565b820191906000526020600020905b81548152906001019060200180831161028757829003601f168201915b505050505081565b60007f000000000000000000000000c290bf292900318eadade782a1f6953f6e13a3316001600160a01b0316636e832f076040518163ffffffff1660e01b8152600401602060405180830381865afa15801561030c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610330919061084d565b905090565b60607f000000000000000000000000c290bf292900318eadade782a1f6953f6e13a3316001600160a01b0316637284e4166040518163ffffffff1660e01b8152600401600060405180830381865afa158015610395573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261033091908101906108f9565b60025460ff161561040a5760405162461bcd60e51b81526020600482015260126024820152711cdc195b1b0b585b1c9958591e4b58d85cdd60721b60448201526064015b60405180910390fd5b6002805460ff1916600190811790915560005460405163168ccd6760e01b81526001600160a01b037f000000000000000000000000be286431454714f511008713973d3b053a2d38f3169263168ccd67926104ad927f000000000000000000000000c290bf292900318eadade782a1f6953f6e13a331927f114a94e507624e00030973aa2e7c5d8f912a92d65868434d704260495c2b3ef892909160040161094a565b6000604051808303816000875af11580156104cc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104f491908101906108f9565b50565b7f00000000000000000000000000000000000000000000000000000000684da7a74211156105675760405162461bcd60e51b815260206004820152601960248201527f5468697320636f6e7472616374206861732065787069726564000000000000006044820152606401610401565b600054156105c55760405162461bcd60e51b815260206004820152602560248201527f54686973207370656c6c2068617320616c7265616479206265656e2073636865604482015264191d5b195960da1b6064820152608401610401565b7f000000000000000000000000be286431454714f511008713973d3b053a2d38f36001600160a01b0316636a42b8f86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106479190610a19565b6106519042610a32565b60008190556040516346d2fbbb60e01b81526001600160a01b037f000000000000000000000000be286431454714f511008713973d3b053a2d38f316916346d2fbbb916106e7917f000000000000000000000000c290bf292900318eadade782a1f6953f6e13a331917f114a94e507624e00030973aa2e7c5d8f912a92d65868434d704260495c2b3ef89160019160040161094a565b600060405180830381600087803b15801561070157600080fd5b505af1158015610715573d6000803e3d6000fd5b50505050565b60008054604051632fc3ef3b60e21b815260048101919091527f000000000000000000000000c290bf292900318eadade782a1f6953f6e13a3316001600160a01b03169063bf0fbcec90602401602060405180830381865afa158015610785573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103309190610a19565b60005b838110156107c45781810151838201526020016107ac565b50506000910152565b600081518084526107e58160208601602086016107a9565b601f01601f19169290920160200192915050565b60208152600061080c60208301846107cd565b9392505050565b600181811c9082168061082757607f821691505b60208210810361084757634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561085f57600080fd5b8151801515811461080c57600080fd5b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156108a0576108a061086f565b604051601f8501601f19908116603f011681019082821181831017156108c8576108c861086f565b816040528093508581528686860111156108e157600080fd5b6108ef8660208301876107a9565b5050509392505050565b60006020828403121561090b57600080fd5b815167ffffffffffffffff81111561092257600080fd5b8201601f8101841361093357600080fd5b61094284825160208401610885565b949350505050565b6001600160a01b03851681526020808201859052608060408301528354600091908290600181811c908281168061098257607f831692505b858310810361099f57634e487b7160e01b85526022600452602485fd5b6080880183905260a088018180156109be57600181146109d4576109ff565b60ff198616825284151560051b820196506109ff565b60008c81526020902060005b868110156109f9578154848201529085019089016109e0565b83019750505b505050505050809250505082606083015295945050505050565b600060208284031215610a2b57600080fd5b5051919050565b80820180821115610a5357634e487b7160e01b600052601160045260246000fd5b9291505056fea26469706673582212202861d3fc4bd9831f3f04e8b5f7b1f4454c061fe9ecb1ecb64c7850ddf1a6bdcb64736f6c63430008100033

Libraries Used


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
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.