ETH Price: $3,194.11 (-0.87%)

Contract

0x44F703D198D8De5504075170BCeecd3FB4DD0F1B
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Cast167200742023-02-27 14:18:35622 days ago1677507515IN
0x44F703D1...FB4DD0F1B
0 ETH0.0345593524.12205663
Schedule166907942023-02-23 11:27:11627 days ago1677151631IN
0x44F703D1...FB4DD0F1B
0 ETH0.0028178830.19784478
0x61010060166831692023-02-22 9:42:23628 days ago1677058943IN
 Create: DssSpell
0 ETH0.1538960628.13324648

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
166831692023-02-22 9:42:23628 days ago1677058943
0x44F703D1...FB4DD0F1B
 Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
DssSpell

Compiler Version
v0.8.16+commit.07a7930e

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, GNU AGPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2023-02-22
*/

// hevm: flattened sources of src/DssSpell.sol
// SPDX-License-Identifier: MIT AND AGPL-3.0-or-later
pragma solidity =0.8.16 >=0.5.12 >=0.8.0 >=0.6.0 <0.9.0 >=0.6.2 <0.9.0 >=0.8.16 <0.9.0;
pragma experimental ABIEncoderV2;

////// lib/dss-exec-lib/lib/forge-std/src/Vm.sol
/* pragma solidity >=0.6.2 <0.9.0; */

/* pragma experimental ABIEncoderV2; */

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

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

    struct Rpc {
        string key;
        string url;
    }

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

    // Loads a storage slot from an address
    function load(address target, bytes32 slot) external view returns (bytes32 data);
    // Signs data
    function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
    // Gets the address for a given private key
    function addr(uint256 privateKey) external pure returns (address keyAddr);
    // Gets the nonce of an account
    function getNonce(address account) external view returns (uint64 nonce);
    // Performs a foreign function call via the terminal
    function ffi(string[] calldata commandInput) external returns (bytes memory result);
    // Sets environment variables
    function setEnv(string calldata name, string calldata value) external;
    // Reads environment variables, (name) => (value)
    function envBool(string calldata name) external view returns (bool value);
    function envUint(string calldata name) external view returns (uint256 value);
    function envInt(string calldata name) external view returns (int256 value);
    function envAddress(string calldata name) external view returns (address value);
    function envBytes32(string calldata name) external view returns (bytes32 value);
    function envString(string calldata name) external view returns (string memory value);
    function envBytes(string calldata name) external view returns (bytes memory value);
    // Reads environment variables as arrays
    function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value);
    function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value);
    function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value);
    function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value);
    function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value);
    function envString(string calldata name, string calldata delim) external view returns (string[] memory value);
    function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value);
    // Read environment variables with default value
    function envOr(string calldata name, bool defaultValue) external returns (bool value);
    function envOr(string calldata name, uint256 defaultValue) external returns (uint256 value);
    function envOr(string calldata name, int256 defaultValue) external returns (int256 value);
    function envOr(string calldata name, address defaultValue) external returns (address value);
    function envOr(string calldata name, bytes32 defaultValue) external returns (bytes32 value);
    function envOr(string calldata name, string calldata defaultValue) external returns (string memory value);
    function envOr(string calldata name, bytes calldata defaultValue) external returns (bytes memory value);
    // Read environment variables as arrays with default value
    function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue)
        external
        returns (bool[] memory value);
    function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue)
        external
        returns (uint256[] memory value);
    function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue)
        external
        returns (int256[] memory value);
    function envOr(string calldata name, string calldata delim, address[] calldata defaultValue)
        external
        returns (address[] memory value);
    function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue)
        external
        returns (bytes32[] memory value);
    function envOr(string calldata name, string calldata delim, string[] calldata defaultValue)
        external
        returns (string[] memory value);
    function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue)
        external
        returns (bytes[] memory value);
    // Records all storage reads and writes
    function record() external;
    // Gets all accessed reads and write slot from a recording session, for a given address
    function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);
    // Gets the _creation_ bytecode from an artifact file. Takes in the relative path to the json file
    function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode);
    // Gets the _deployed_ bytecode from an artifact file. Takes in the relative path to the json file
    function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode);
    // Labels an address in call traces
    function label(address account, string calldata newLabel) external;
    // Using the address that calls the test contract, has the next call (at this call depth only) create a transaction that can later be signed and sent onchain
    function broadcast() external;
    // Has the next call (at this call depth only) create a transaction with the address provided as the sender that can later be signed and sent onchain
    function broadcast(address signer) external;
    // Has the next call (at this call depth only) create a transaction with the private key provided as the sender that can later be signed and sent onchain
    function broadcast(uint256 privateKey) external;
    // Using the address that calls the test contract, has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain
    function startBroadcast() external;
    // Has all subsequent calls (at this call depth only) create transactions with the address provided that can later be signed and sent onchain
    function startBroadcast(address signer) external;
    // Has all subsequent calls (at this call depth only) create transactions with the private key provided that can later be signed and sent onchain
    function startBroadcast(uint256 privateKey) external;
    // Stops collecting onchain transactions
    function stopBroadcast() external;
    // Reads the entire content of file to string
    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);
    // Get the path of the current project root
    function projectRoot() external view returns (string memory path);
    // Get the metadata for a file/directory
    function fsMetadata(string calldata fileOrDir) external returns (FsMetadata memory metadata);
    // Reads next line of file to string
    function readLine(string calldata path) external view returns (string memory line);
    // Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.
    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.
    function writeLine(string calldata path, string calldata data) external;
    // Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.
    function closeFile(string calldata path) external;
    // Removes file. 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.
    function removeFile(string calldata path) external;
    // Convert values to a string
    function toString(address value) external pure returns (string memory stringifiedValue);
    function toString(bytes calldata value) external pure returns (string memory stringifiedValue);
    function toString(bytes32 value) external pure returns (string memory stringifiedValue);
    function toString(bool value) external pure returns (string memory stringifiedValue);
    function toString(uint256 value) external pure returns (string memory stringifiedValue);
    function toString(int256 value) external pure returns (string memory stringifiedValue);
    // Convert values from a string
    function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue);
    function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue);
    function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue);
    function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue);
    function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue);
    function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue);
    // Record all the transaction logs
    function recordLogs() external;
    // Gets all the recorded logs
    function getRecordedLogs() external returns (Log[] memory logs);
    // Derive a private key from a provided mnenomic string (or mnenomic file path) at the derivation path m/44'/60'/0'/0/{index}
    function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey);
    // Derive a private key from a provided mnenomic string (or mnenomic file path) at {derivationPath}{index}
    function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index)
        external
        pure
        returns (uint256 privateKey);
    // Adds a private key to the local forge wallet and returns the address
    function rememberKey(uint256 privateKey) external returns (address keyAddr);
    //
    // parseJson
    //
    // ----
    // In case the returned value is a JSON object, it's encoded as a ABI-encoded tuple. As JSON objects
    // don't have the notion of ordered, but tuples do, they JSON object is encoded with it's fields ordered in
    // ALPHABETICAL order. That means that in order to successfully decode the tuple, we need to define a tuple that
    // encodes the fields in the same order, which is alphabetical. In the case of Solidity structs, they are encoded
    // as tuples, with the attributes in the order in which they are defined.
    // For example: json = { 'a': 1, 'b': 0xa4tb......3xs}
    // a: uint256
    // b: address
    // To decode that json, we need to define a struct or a tuple as follows:
    // struct json = { uint256 a; address b; }
    // If we defined a json struct with the opposite order, meaning placing the address b first, it would try to
    // decode the tuple in that order, and thus fail.
    // ----
    // Given a string of JSON, return it as ABI-encoded
    function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData);
    function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData);

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

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

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

    //
    // writeJson
    //
    // ----
    // Write a serialized JSON object to a file. If the file exists, it will be overwritten.
    // Let's assume we want to write the following JSON to a file:
    //
    // { "boolean": true, "number": 342, "object": { "title": "finally json serialization" } }
    //
    // ```
    //  string memory json1 = "some key";
    //  vm.serializeBool(json1, "boolean", true);
    //  vm.serializeBool(json1, "number", uint256(342));
    //  json2 = "some other key";
    //  string memory output = vm.serializeString(json2, "title", "finally json serialization");
    //  string memory finalJson = vm.serialize(json1, "object", output);
    //  vm.writeJson(finalJson, "./output/example.json");
    // ```
    // The critical insight is that every invocation of serialization will return the stringified version of the JSON
    // up to that point. That means we can construct arbitrary JSON objects and then use the return stringified version
    // to serialize them as values to another JSON object.
    //
    // json1 and json2 are simply keys used by the backend to keep track of the objects. So vm.serializeJson(json1,..)
    // will find the object in-memory that is keyed by "some key".
    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;
    // Returns the RPC url for the given alias
    function rpcUrl(string calldata rpcAlias) external view returns (string memory json);
    // Returns all rpc urls and their aliases `[alias, url][]`
    function rpcUrls() external view returns (string[2][] memory urls);
    // Returns all rpc urls and their aliases as structs.
    function rpcUrlStructs() external view returns (Rpc[] memory urls);
    // If the condition is false, discard this run's fuzz inputs and generate new ones.
    function assume(bool condition) external pure;
    // Pauses gas metering (i.e. gas usage is not counted). Noop if already paused.
    function pauseGasMetering() external;
    // Resumes gas metering (i.e. gas usage is counted again). Noop if already on.
    function resumeGasMetering() external;
}

interface Vm is VmSafe {
    // Sets block.timestamp
    function warp(uint256 newTimestamp) external;
    // Sets block.height
    function roll(uint256 newHeight) external;
    // Sets block.basefee
    function fee(uint256 newBasefee) external;
    // Sets block.difficulty
    function difficulty(uint256 newDifficulty) external;
    // Sets block.chainid
    function chainId(uint256 newChainId) external;
    // Stores a value to an address' storage slot.
    function store(address target, bytes32 slot, bytes32 value) 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 *next* call's msg.sender to be the input address
    function prank(address msgSender) external;
    // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called
    function startPrank(address msgSender) external;
    // Sets the *next* call's msg.sender to be the input address, and the tx.origin to be the second input
    function prank(address msgSender, address txOrigin) external;
    // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called, and the tx.origin to be the second input
    function startPrank(address msgSender, address txOrigin) external;
    // Resets subsequent calls' msg.sender to be `address(this)`
    function stopPrank() external;
    // Sets an address' balance
    function deal(address account, uint256 newBalance) external;
    // Sets an address' code
    function etch(address target, bytes calldata newRuntimeBytecode) external;
    // Expects an error on next call
    function expectRevert(bytes calldata revertData) external;
    function expectRevert(bytes4 revertData) external;
    function expectRevert() 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;
    function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter)
        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;
    // Clears all mocked calls
    function clearMockedCalls() 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 a call to an address with the specified msg.value and calldata
    function expectCall(address callee, uint256 msgValue, bytes calldata data) external;
    // Sets block.coinbase
    function coinbase(address newCoinbase) 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);
    // Revert the state of the EVM to a previous snapshot
    // Takes the snapshot id to revert to.
    // This deletes the snapshot and all snapshots taken after the given snapshot id.
    function revertTo(uint256 snapshotId) external returns (bool success);
    // Creates a new fork with the given endpoint and block and returns the identifier of the fork
    function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);
    // Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork
    function createFork(string calldata urlOrAlias) external returns (uint256 forkId);
    // Creates a new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before the transaction,
    // and returns the identifier of the fork
    function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);
    // Creates _and_ also selects a new fork with the given endpoint and block and returns the identifier of the fork
    function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);
    // Creates _and_ also selects new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before
    // the transaction, returns the identifier of the fork
    function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);
    // Creates _and_ also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork
    function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId);
    // Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.
    function selectFork(uint256 forkId) external;
    /// Returns the identifier of the currently active fork. Reverts if no fork is currently active.
    function activeFork() external view returns (uint256 forkId);
    // Updates the currently active fork to given block number
    // This is similar to `roll` but for the currently active fork
    function rollFork(uint256 blockNumber) external;
    // Updates the currently active fork to given transaction
    // this will `rollFork` with the number of the block the transaction was mined in and replays all transaction mined before it in the block
    function rollFork(bytes32 txHash) external;
    // Updates the given fork to given block number
    function rollFork(uint256 forkId, uint256 blockNumber) external;
    // Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block
    function rollFork(uint256 forkId, bytes32 txHash) external;
    // Marks that the account(s) should use persistent storage across fork swaps in a multifork setup
    // Meaning, changes made to the state of this account will be kept when switching forks
    function makePersistent(address account) external;
    function makePersistent(address account0, address account1) external;
    function makePersistent(address account0, address account1, address account2) external;
    function makePersistent(address[] calldata accounts) external;
    // Revokes persistent status from the address, previously added via `makePersistent`
    function revokePersistent(address account) external;
    function revokePersistent(address[] calldata accounts) external;
    // Returns true if the account is marked as persistent
    function isPersistent(address account) external view returns (bool persistent);
    // In forking mode, explicitly grant the given address cheatcode access
    function allowCheatcodes(address account) 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;
}

////// lib/dss-exec-lib/lib/forge-std/src/StdJson.sol
/* pragma solidity >=0.6.0 <0.9.0; */

/* pragma experimental ABIEncoderV2; */

/* import {VmSafe} from "./Vm.sol"; */

// Helpers for parsing and writing JSON files
// To parse:
// ```
// using stdJson for string;
// string memory json = vm.readFile("some_peth");
// json.parseUint("<json_path>");
// ```
// To write:
// ```
// using stdJson for string;
// string memory json = "deploymentArtifact";
// Contract contract = new Contract();
// json.serialize("contractAddress", address(contract));
// json = json.serialize("deploymentTimes", uint(1));
// // store the stringified JSON to the 'json' variable we have been using as a key
// // as we won't need it any longer
// string memory json2 = "finalArtifact";
// string memory final = json2.serialize("depArtifact", json);
// final.write("<some_path>");
// ```

library stdJson {
    VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));

    function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) {
        return vm.parseJson(json, key);
    }

    function readUint(string memory json, string memory key) internal pure returns (uint256) {
        return abi.decode(vm.parseJson(json, key), (uint256));
    }

    function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) {
        return abi.decode(vm.parseJson(json, key), (uint256[]));
    }

    function readInt(string memory json, string memory key) internal pure returns (int256) {
        return abi.decode(vm.parseJson(json, key), (int256));
    }

    function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) {
        return abi.decode(vm.parseJson(json, key), (int256[]));
    }

    function readBytes32(string memory json, string memory key) internal pure returns (bytes32) {
        return abi.decode(vm.parseJson(json, key), (bytes32));
    }

    function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) {
        return abi.decode(vm.parseJson(json, key), (bytes32[]));
    }

    function readString(string memory json, string memory key) internal pure returns (string memory) {
        return abi.decode(vm.parseJson(json, key), (string));
    }

    function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) {
        return abi.decode(vm.parseJson(json, key), (string[]));
    }

    function readAddress(string memory json, string memory key) internal pure returns (address) {
        return abi.decode(vm.parseJson(json, key), (address));
    }

    function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) {
        return abi.decode(vm.parseJson(json, key), (address[]));
    }

    function readBool(string memory json, string memory key) internal pure returns (bool) {
        return abi.decode(vm.parseJson(json, key), (bool));
    }

    function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) {
        return abi.decode(vm.parseJson(json, key), (bool[]));
    }

    function readBytes(string memory json, string memory key) internal pure returns (bytes memory) {
        return abi.decode(vm.parseJson(json, key), (bytes));
    }

    function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) {
        return abi.decode(vm.parseJson(json, key), (bytes[]));
    }

    function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {
        return vm.serializeBool(jsonKey, key, value);
    }

    function serialize(string memory jsonKey, string memory key, bool[] memory value)
        internal
        returns (string memory)
    {
        return vm.serializeBool(jsonKey, key, value);
    }

    function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {
        return vm.serializeUint(jsonKey, key, value);
    }

    function serialize(string memory jsonKey, string memory key, uint256[] memory value)
        internal
        returns (string memory)
    {
        return vm.serializeUint(jsonKey, key, value);
    }

    function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {
        return vm.serializeInt(jsonKey, key, value);
    }

    function serialize(string memory jsonKey, string memory key, int256[] memory value)
        internal
        returns (string memory)
    {
        return vm.serializeInt(jsonKey, key, value);
    }

    function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {
        return vm.serializeAddress(jsonKey, key, value);
    }

    function serialize(string memory jsonKey, string memory key, address[] memory value)
        internal
        returns (string memory)
    {
        return vm.serializeAddress(jsonKey, key, value);
    }

    function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {
        return vm.serializeBytes32(jsonKey, key, value);
    }

    function serialize(string memory jsonKey, string memory key, bytes32[] memory value)
        internal
        returns (string memory)
    {
        return vm.serializeBytes32(jsonKey, key, value);
    }

    function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {
        return vm.serializeBytes(jsonKey, key, value);
    }

    function serialize(string memory jsonKey, string memory key, bytes[] memory value)
        internal
        returns (string memory)
    {
        return vm.serializeBytes(jsonKey, key, value);
    }

    function serialize(string memory jsonKey, string memory key, string memory value)
        internal
        returns (string memory)
    {
        return vm.serializeString(jsonKey, key, value);
    }

    function serialize(string memory jsonKey, string memory key, string[] memory value)
        internal
        returns (string memory)
    {
        return vm.serializeString(jsonKey, key, value);
    }

    function write(string memory jsonKey, string memory path) internal {
        vm.writeJson(jsonKey, path);
    }

    function write(string memory jsonKey, string memory path, string memory valueKey) internal {
        vm.writeJson(jsonKey, path, valueKey);
    }
}

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

/* pragma solidity ^0.8.16; */

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

/* pragma solidity ^0.8.16; */

/* import { CollateralOpts } from "./CollateralOpts.sol"; */

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_2 {
    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_2(_oracle).orb1(), _oracle);
        } else {
            // Standard OSM
            addReaderToWhitelistCall(OracleLike_2(_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_2(_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_2(_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_2(_median).setBar(_minQuorum);
    }
    /**
        @dev Add OSM address to OSM mom, allowing it to be frozen by governance.
        @param _osm        Oracle Security Module (OSM) core contract address
        @param _ilk        Collateral type using OSM
    */
    function allowOSMFreeze(address _osm, bytes32 _ilk) public {
        MomLike(osmMom()).setOsm(_ilk, _osm);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

////// lib/dss-exec-lib/src/DssAction.sol
//
// DssAction.sol -- DSS Executive Spell Actions
//
// Copyright (C) 2020-2022 Dai Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

/* pragma solidity ^0.8.16; */

/* import { DssExecLib } from "./DssExecLib.sol"; */
/* import { CollateralOpts } from "./CollateralOpts.sol"; */

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

/* pragma solidity ^0.8.16; */

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/ERC/GemAbstract.sol
/* pragma solidity >=0.5.12; */

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

////// lib/dss-test/lib/dss-interfaces/src/dapp/DSAuthorityAbstract.sol
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

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

/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

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

////// lib/dss-test/lib/dss-interfaces/src/dss/AuthGemJoinAbstract.sol
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

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

/* pragma solidity >=0.5.12; */

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
/* pragma solidity >=0.5.12; */

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

////// lib/dss-test/lib/dss-interfaces/src/dss/CureAbstract.sol
/* pragma solidity >=0.5.12; */

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

////// lib/dss-test/lib/dss-interfaces/src/dss/DaiAbstract.sol
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

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

/* pragma solidity >=0.5.12; */

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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

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

////// lib/dss-test/lib/dss-interfaces/src/dss/ESMAbstract.sol
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

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

/* pragma solidity >=0.5.12; */

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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

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

////// lib/dss-test/lib/dss-interfaces/src/dss/GemJoinAbstract.sol
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// https://github.com/makerdao/dss-gem-joins/blob/master/src/join-managed.sol
interface GemJoinManagedAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function vat() external view returns (address);
    function ilk() external view returns (bytes32);
    function gem() external view returns (address);
    function dec() external view returns (uint256);
    function live() external view returns (uint256);
    function cage() external;
    function join(address, uint256) external;
    function exit(address, address, uint256) external;
}

////// lib/dss-test/lib/dss-interfaces/src/dss/GetCdpsAbstract.sol
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

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

/* pragma solidity >=0.5.12; */

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

////// lib/dss-test/lib/dss-interfaces/src/dss/MedianAbstract.sol
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

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

////// lib/dss-test/lib/dss-interfaces/src/dss/SpotAbstract.sol
/* pragma solidity >=0.5.12; */

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

/* pragma solidity >=0.5.12; */

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

////// lib/dss-test/lib/dss-interfaces/src/dss/VatAbstract.sol
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

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

////// lib/dss-test/lib/dss-interfaces/src/dss/VowAbstract.sol
/* pragma solidity >=0.5.12; */

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

////// lib/dss-test/lib/dss-interfaces/src/dss/mip21/RwaInputConduitAbstract.sol
// SPDX-FileCopyrightText: © 2022 Dai Foundation <www.daifoundation.org>
/* pragma solidity >=0.5.12; */

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>
/* pragma solidity >=0.5.12; */

// 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>
/* pragma solidity >=0.5.12; */

// 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>
/* pragma solidity >=0.5.12; */

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>
/* pragma solidity >=0.5.12; */

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

////// lib/dss-test/lib/dss-interfaces/src/sai/GemPitAbstract.sol
/* pragma solidity >=0.5.12; */

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

////// lib/dss-test/lib/dss-interfaces/src/sai/SaiMomAbstract.sol
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

// 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
/* pragma solidity >=0.5.12; */

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

////// lib/dss-test/lib/dss-interfaces/src/utils/WardsAbstract.sol
/* pragma solidity >=0.5.12; */

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

////// lib/dss-test/lib/dss-interfaces/src/Interfaces.sol
/* pragma solidity >=0.5.12; */

/* import { GemAbstract } from "./ERC/GemAbstract.sol"; */

/* import { DSAuthorityAbstract, DSAuthAbstract } from "./dapp/DSAuthorityAbstract.sol"; */
/* import { DSChiefAbstract } from "./dapp/DSChiefAbstract.sol"; */
/* import { DSPauseAbstract } from "./dapp/DSPauseAbstract.sol"; */
/* import { DSPauseProxyAbstract } from "./dapp/DSPauseProxyAbstract.sol"; */
/* import { DSRolesAbstract } from "./dapp/DSRolesAbstract.sol"; */
/* import { DSSpellAbstract } from "./dapp/DSSpellAbstract.sol"; */
/* import { DSRuneAbstract } from "./dapp/DSRuneAbstract.sol"; */
/* import { DSThingAbstract } from "./dapp/DSThingAbstract.sol"; */
/* import { DSTokenAbstract } from "./dapp/DSTokenAbstract.sol"; */
/* import { DSValueAbstract } from "./dapp/DSValueAbstract.sol"; */

/* import { AuthGemJoinAbstract } from "./dss/AuthGemJoinAbstract.sol"; */
/* import { CatAbstract } from "./dss/CatAbstract.sol"; */
/* import { ChainlogAbstract } from "./dss/ChainlogAbstract.sol"; */
/* import { ChainlogHelper } from "./dss/ChainlogAbstract.sol"; */
/* import { ClipAbstract } from "./dss/ClipAbstract.sol"; */
/* import { ClipperMomAbstract } from "./dss/ClipperMomAbstract.sol"; */
/* import { CureAbstract } from "./dss/CureAbstract.sol"; */
/* import { DaiAbstract } from "./dss/DaiAbstract.sol"; */
/* import { DaiJoinAbstract } from "./dss/DaiJoinAbstract.sol"; */
/* import { DogAbstract } from "./dss/DogAbstract.sol"; */
/* import { DssAutoLineAbstract } from "./dss/DssAutoLineAbstract.sol"; */
/* import { DssCdpManagerAbstract } from "./dss/DssCdpManager.sol"; */
/* import { EndAbstract } from "./dss/EndAbstract.sol"; */
/* import { ESMAbstract } from "./dss/ESMAbstract.sol"; */
/* import { ETHJoinAbstract } from "./dss/ETHJoinAbstract.sol"; */
/* import { ExponentialDecreaseAbstract } from "./dss/ExponentialDecreaseAbstract.sol"; */
/* import { FaucetAbstract } from "./dss/FaucetAbstract.sol"; */
/* import { FlapAbstract } from "./dss/FlapAbstract.sol"; */
/* import { FlashAbstract } from "./dss/FlashAbstract.sol"; */
/* import { FlipAbstract } from "./dss/FlipAbstract.sol"; */
/* import { FlipperMomAbstract } from "./dss/FlipperMomAbstract.sol"; */
/* import { FlopAbstract } from "./dss/FlopAbstract.sol"; */
/* import { GemJoinAbstract } from "./dss/GemJoinAbstract.sol"; */
/* import { GemJoinImplementationAbstract } from "./dss/GemJoinImplementationAbstract.sol"; */
/* import { GemJoinManagedAbstract } from "./dss/GemJoinManagedAbstract.sol"; */
/* import { GetCdpsAbstract } from "./dss/GetCdpsAbstract.sol"; */
/* import { IlkRegistryAbstract } from "./dss/IlkRegistryAbstract.sol"; */
/* import { JugAbstract } from "./dss/JugAbstract.sol"; */
/* import { LerpAbstract } from "./dss/LerpAbstract.sol"; */
/* import { LerpFactoryAbstract } from "./dss/LerpFactoryAbstract.sol"; */
/* import { LinearDecreaseAbstract } from "./dss/LinearDecreaseAbstract.sol"; */
/* import { LPOsmAbstract } from "./dss/LPOsmAbstract.sol"; */
/* import { MkrAuthorityAbstract } from "./dss/MkrAuthorityAbstract.sol"; */
/* import { MedianAbstract } from "./dss/MedianAbstract.sol"; */
/* import { OsmAbstract } from "./dss/OsmAbstract.sol"; */
/* import { OsmMomAbstract } from "./dss/OsmMomAbstract.sol"; */
/* import { PotAbstract } from "./dss/PotAbstract.sol"; */
/* import { PsmAbstract } from "./dss/PsmAbstract.sol"; */
/* import { SpotAbstract } from "./dss/SpotAbstract.sol"; */
/* import { StairstepExponentialDecreaseAbstract } from "./dss/StairstepExponentialDecreaseAbstract.sol"; */
/* import { VatAbstract } from "./dss/VatAbstract.sol"; */
/* import { VestAbstract } from "./dss/VestAbstract.sol"; */
/* import { VowAbstract } from "./dss/VowAbstract.sol"; */

// MIP21 Abstracts
/* import {
  RwaInputConduitBaseAbstract,
  RwaInputConduitAbstract,
  RwaInputConduit2Abstract,
  RwaInputConduit3Abstract
} from "./dss/mip21/RwaInputConduitAbstract.sol"; */
/* import { RwaJarAbstract } from "./dss/mip21/RwaJarAbstract.sol"; */
/* import { RwaLiquidationOracleAbstract } from "./dss/mip21/RwaLiquidationOracleAbstract.sol"; */
/* import {
  RwaOutputConduitBaseAbstract,
  RwaOutputConduitAbstract,
  RwaOutputConduit2Abstract,
  RwaOutputConduit3Abstract
} from "./dss/mip21/RwaOutputConduitAbstract.sol"; */
/* import { RwaUrnAbstract } from "./dss/mip21/RwaUrnAbstract.sol"; */

/* import { GemPitAbstract } from "./sai/GemPitAbstract.sol"; */
/* import { SaiMomAbstract } from "./sai/SaiMomAbstract.sol"; */
/* import { SaiTapAbstract } from "./sai/SaiTapAbstract.sol"; */
/* import { SaiTopAbstract } from "./sai/SaiTopAbstract.sol"; */
/* import { SaiTubAbstract } from "./sai/SaiTubAbstract.sol"; */
/* import { SaiVoxAbstract } from "./sai/SaiVoxAbstract.sol"; */

// Partial DSS Abstracts
/* import { WardsAbstract } from "./utils/WardsAbstract.sol"; */

////// 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/>.
/* pragma solidity >=0.8.0; */

/* import {
    WardsAbstract,
    DSTokenAbstract,
    DaiAbstract,
    VatAbstract
} from "dss-interfaces/Interfaces.sol"; */
/* import {Vm} from "forge-std/Vm.sol"; */

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/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/>.
/* pragma solidity >=0.8.0; */

/* import "dss-interfaces/Interfaces.sol"; */

/* import {GodMode} from "./GodMode.sol"; */
/* import {DssInstance} from "./MCD.sol"; */

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

}

////// 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/>.
/* pragma solidity >=0.8.0; */

/* import "dss-interfaces/Interfaces.sol"; */

/* import {MCDUser} from "./MCDUser.sol"; */
/* import {GodMode} from "./GodMode.sol"; */

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/ScriptTools.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/>.
/* pragma solidity >=0.8.0; */

/* import { VmSafe } from "forge-std/Vm.sol"; */
/* import { stdJson } from "forge-std/StdJson.sol"; */

/* import { WardsAbstract } from "dss-interfaces/Interfaces.sol"; */

/** 
 * @title Script Tools
 * @dev Contains opinionated tools used in scripts.
 */
library ScriptTools {

    VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
    
    string internal constant DEFAULT_DELIMITER = ",";
    string internal constant DELIMITER_OVERRIDE = "DSSTEST_ARRAY_DELIMITER";
    string internal constant EXPORT_JSON_KEY = "EXPORTS";

    function getRootChainId() internal view returns (uint256) {
        return vm.envUint("FOUNDRY_ROOT_CHAINID");
    }

    function readInput(string memory name) internal view returns (string memory) {
        string memory root = vm.projectRoot();
        return readInput(root, name);
    }

    function readInput(string memory root, string memory name) internal view returns (string memory) {
        string memory chainInputFolder = string(abi.encodePacked("/script/input/", vm.toString(getRootChainId()), "/"));
        return vm.readFile(string(abi.encodePacked(root, chainInputFolder, name, ".json")));
    }

    function readOutput(string memory name, uint256 timestamp) internal view returns (string memory) {
        string memory root = vm.projectRoot();
        string memory chainOutputFolder = string(abi.encodePacked("/script/output/", vm.toString(getRootChainId()), "/"));
        return vm.readFile(string(abi.encodePacked(root, chainOutputFolder, name, "-", vm.toString(timestamp), ".json")));
    }

    function readOutput(string memory name) internal view returns (string memory) {
        string memory root = vm.projectRoot();
        string memory chainOutputFolder = string(abi.encodePacked("/script/output/", vm.toString(getRootChainId()), "/"));
        return vm.readFile(string(abi.encodePacked(root, chainOutputFolder, name, "-latest.json")));
    }
    
    /**
     * @notice Use standard environment variables to load config.
     * @dev Will first check FOUNDRY_SCRIPT_CONFIG_TEXT for raw json text.
     *      Falls back to FOUNDRY_SCRIPT_CONFIG for a standard file definition.
     *      Finally will fall back to the given string `name`.
     * @param name The default config file to load if no environment variables are set.
     * @return config The raw json text of the config.
     */
    function loadConfig(string memory name) internal returns (string memory config) {
        config = vm.envOr("FOUNDRY_SCRIPT_CONFIG_TEXT", string(""));
        if (eq(config, "")) {
            config = readInput(vm.envOr("FOUNDRY_SCRIPT_CONFIG", name));
        }
    }
    
    /**
     * @notice Use standard environment variables to load config.
     * @dev Will first check FOUNDRY_SCRIPT_CONFIG_TEXT for raw json text.
     *      Falls back to FOUNDRY_SCRIPT_CONFIG for a standard file definition.
     *      Finally will revert if no environment variables are set.
     * @return config The raw json text of the config.
     */
    function loadConfig() internal returns (string memory config) {
        config = vm.envOr("FOUNDRY_SCRIPT_CONFIG_TEXT", string(""));
        if (eq(config, "")) {
            config = readInput(vm.envString("FOUNDRY_SCRIPT_CONFIG"));
        }
    }
    
    /**
     * @notice Use standard environment variables to load dependencies.
     * @dev Will first check FOUNDRY_SCRIPT_DEPS_TEXT for raw json text.
     *      Falls back to FOUNDRY_SCRIPT_DEPS for a standard file definition.
     *      Finally will fall back to the given string `name`.
     * @param name The default dependency file to load if no environment variables are set.
     * @return dependencies The raw json text of the dependencies.
     */
    function loadDependencies(string memory name) internal returns (string memory dependencies) {
        dependencies = vm.envOr("FOUNDRY_SCRIPT_DEPS_TEXT", string(""));
        if (eq(dependencies, "")) {
            dependencies = readOutput(vm.envOr("FOUNDRY_SCRIPT_DEPS", name));
        }
    }
    
    /**
     * @notice Use standard environment variables to load dependencies.
     * @dev Will first check FOUNDRY_SCRIPT_DEPS_TEXT for raw json text.
     *      Falls back to FOUNDRY_SCRIPT_DEPS for a standard file definition.
     *      Finally will revert if no environment variables are set.
     * @return dependencies The raw json text of the dependencies.
     */
    function loadDependencies() internal returns (string memory dependencies) {
        dependencies = vm.envOr("FOUNDRY_SCRIPT_DEPS_TEXT", string(""));
        if (eq(dependencies, "")) {
            dependencies = readOutput(vm.envString("FOUNDRY_SCRIPT_DEPS"));
        }
    }

    /**
     * @notice Used to export important contracts to higher level deploy scripts.
     *         Note waiting on Foundry to have better primitives, but roll our own for now.
     * @dev Set FOUNDRY_EXPORTS_NAME to override the name of the json file.
     * @param name The name to give the json file.
     * @param label The label of the address.
     * @param addr The address to export.
     */
    function exportContract(string memory name, string memory label, address addr) internal {
        name = vm.envOr("FOUNDRY_EXPORTS_NAME", name);
        string memory json = vm.serializeAddress(EXPORT_JSON_KEY, label, addr);
        string memory root = vm.projectRoot();
        string memory chainOutputFolder = string(abi.encodePacked("/script/output/", vm.toString(getRootChainId()), "/"));
        vm.writeJson(json, string(abi.encodePacked(root, chainOutputFolder, name, "-", vm.toString(block.timestamp), ".json")));
        if (vm.envOr("FOUNDRY_EXPORTS_OVERWRITE_LATEST", false)) {
            vm.writeJson(json, string(abi.encodePacked(root, chainOutputFolder, name, "-latest.json")));
        }
    }

    /**
     * @notice Used to export important contracts to higher level deploy scripts.
     *         Note waiting on Foundry to have better primitives, but roll our own for now.
     * @dev Requires FOUNDRY_EXPORTS_NAME to be set.
     * @param label The label of the address.
     * @param addr The address to export.
     */
    function exportContract(string memory label, address addr) internal {
        exportContract(vm.envString("FOUNDRY_EXPORTS_NAME"), label, addr);
    }

    /**
     * @notice It's common to define strings as bytes32 (such as for ilks)
     */
    function stringToBytes32(string memory source) internal pure returns (bytes32 result) {
        bytes memory emptyStringTest = bytes(source);
        if (emptyStringTest.length == 0) {
            return 0x0;
        }

        assembly {
            result := mload(add(source, 32))
        }
    }

    /**
     * @notice Convert an ilk to a chainlog key by replacing all dashes with underscores.
     *         Ex) Convert "ETH-A" to "ETH_A"
     */
    function ilkToChainlogFormat(bytes32 ilk) internal pure returns (string memory) {
        uint256 len = 0;
        for (; len < 32; len++) {
            if (uint8(ilk[len]) == 0x00) break;
        }
        bytes memory result = new bytes(len);
        for (uint256 i = 0; i < len; i++) {
            uint8 b = uint8(ilk[i]);
            if (b == 0x2d) result[i] = bytes1(0x5f);
            else result[i] = bytes1(b);
        }
        return string(result);
    }

    function eq(string memory a, string memory b) internal pure returns (bool) {
        return keccak256(bytes(a)) == keccak256(bytes(b));
    }

    function switchOwner(address base, address deployer, address newOwner) internal {
        if (deployer == newOwner) return;
        require(WardsAbstract(base).wards(deployer) == 1, "deployer-not-authed");
        WardsAbstract(base).rely(newOwner);
        WardsAbstract(base).deny(deployer);
    }

    // Read config variable, but allow for an environment variable override

    function readUint(string memory json, string memory key, string memory envKey) internal returns (uint256) {
        return vm.envOr(envKey, stdJson.readUint(json, key));
    }

    function readUintArray(string memory json, string memory key, string memory envKey) internal returns (uint256[] memory) {
        return vm.envOr(envKey, vm.envOr(DELIMITER_OVERRIDE, DEFAULT_DELIMITER), stdJson.readUintArray(json, key));
    }

    function readInt(string memory json, string memory key, string memory envKey) internal returns (int256) {
        return vm.envOr(envKey, stdJson.readInt(json, key));
    }

    function readIntArray(string memory json, string memory key, string memory envKey) internal returns (int256[] memory) {
        return vm.envOr(envKey, vm.envOr(DELIMITER_OVERRIDE, DEFAULT_DELIMITER), stdJson.readIntArray(json, key));
    }

    function readBytes32(string memory json, string memory key, string memory envKey) internal returns (bytes32) {
        return vm.envOr(envKey, stdJson.readBytes32(json, key));
    }

    function readBytes32Array(string memory json, string memory key, string memory envKey) internal returns (bytes32[] memory) {
        return vm.envOr(envKey, vm.envOr(DELIMITER_OVERRIDE, DEFAULT_DELIMITER), stdJson.readBytes32Array(json, key));
    }

    function readString(string memory json, string memory key, string memory envKey) internal returns (string memory) {
        return vm.envOr(envKey, stdJson.readString(json, key));
    }

    function readStringArray(string memory json, string memory key, string memory envKey) internal returns (string[] memory) {
        return vm.envOr(envKey, vm.envOr(DELIMITER_OVERRIDE, DEFAULT_DELIMITER), stdJson.readStringArray(json, key));
    }

    function readAddress(string memory json, string memory key, string memory envKey) internal returns (address) {
        return vm.envOr(envKey, stdJson.readAddress(json, key));
    }

    function readAddressArray(string memory json, string memory key, string memory envKey) internal returns (address[] memory) {
        return vm.envOr(envKey, vm.envOr(DELIMITER_OVERRIDE, DEFAULT_DELIMITER), stdJson.readAddressArray(json, key));
    }

    function readBool(string memory json, string memory key, string memory envKey) internal returns (bool) {
        return vm.envOr(envKey, stdJson.readBool(json, key));
    }

    function readBoolArray(string memory json, string memory key, string memory envKey) internal returns (bool[] memory) {
        return vm.envOr(envKey, vm.envOr(DELIMITER_OVERRIDE, DEFAULT_DELIMITER), stdJson.readBoolArray(json, key));
    }

    function readBytes(string memory json, string memory key, string memory envKey) internal returns (bytes memory) {
        return vm.envOr(envKey, stdJson.readBytes(json, key));
    }

    function readBytesArray(string memory json, string memory key, string memory envKey) internal returns (bytes[] memory) {
        return vm.envOr(envKey, vm.envOr(DELIMITER_OVERRIDE, DEFAULT_DELIMITER), stdJson.readBytesArray(json, key));
    }

}

////// src/dependencies/dss-direct-deposit/D3MCoreInstance.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/>.

/* pragma solidity >=0.8.0; */

struct D3MCoreInstance {
    address hub;
    address mom;
}

////// src/dependencies/dss-direct-deposit/D3MInstance.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/>.

/* pragma solidity >=0.8.0; */

struct D3MInstance {
    address plan;
    address pool;
    address oracle;
}

////// src/dependencies/dss-direct-deposit/D3MInit.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/>.

/* pragma solidity >=0.8.0; */

/* import "dss-interfaces/dss/DssAutoLineAbstract.sol"; */
/* import "dss-interfaces/dss/IlkRegistryAbstract.sol"; */
/* import "dss-interfaces/ERC/GemAbstract.sol"; */
/* import { DssInstance } from "dss-test/MCD.sol"; */
/* import { ScriptTools } from "dss-test/ScriptTools.sol"; */

/* import { D3MInstance } from "./D3MInstance.sol"; */
/* import { D3MCoreInstance } from "./D3MCoreInstance.sol"; */

interface AavePoolLike {
    function hub() external view returns (address);
    function dai() external view returns (address);
    function ilk() external view returns (bytes32);
    function vat() external view returns (address);
    function file(bytes32, address) external;
    function adai() external view returns (address);
    function stableDebt() external view returns (address);
    function variableDebt() external view returns (address);
}

interface AavePlanLike {
    function rely(address) external;
    function file(bytes32, uint256) external;
    function adai() external view returns (address);
    function stableDebt() external view returns (address);
    function variableDebt() external view returns (address);
    function tack() external view returns (address);
    function adaiRevision() external view returns (uint256);
}

interface ADaiLike {
    function ATOKEN_REVISION() external view returns (uint256);
}

interface CompoundPoolLike {
    function hub() external view returns (address);
    function dai() external view returns (address);
    function ilk() external view returns (bytes32);
    function vat() external view returns (address);
    function file(bytes32, address) external;
    function cDai() external view returns (address);
    function comptroller() external view returns (address);
    function comp() external view returns (address);
}

interface CompoundPlanLike {
    function rely(address) external;
    function file(bytes32, uint256) external;
    function tack() external view returns (address);
    function delegate() external view returns (address);
    function cDai() external view returns (address);
}

interface CDaiLike {
    function interestRateModel() external view returns (address);
    function implementation() external view returns (address);
}

interface D3MOracleLike_2 {
    function vat() external view returns (address);
    function ilk() external view returns (bytes32);
    function file(bytes32, address) external;
}

interface D3MHubLike_2 {
    function vat() external view returns (address);
    function daiJoin() external view returns (address);
    function file(bytes32, address) external;
    function file(bytes32, bytes32, address) external;
    function file(bytes32, bytes32, uint256) external;
}

interface D3MMomLike_2 {
    function setAuthority(address) external;
}

struct D3MCommonConfig {
    address hub;
    address mom;
    bytes32 ilk;
    bool existingIlk;
    uint256 maxLine;
    uint256 gap;
    uint256 ttl;
    uint256 tau;
}

struct D3MAaveConfig {
    address king;
    uint256 bar;
    address adai;
    address stableDebt;
    address variableDebt;
    address tack;
    uint256 adaiRevision;
}

struct D3MCompoundConfig {
    address king;
    uint256 barb;
    address cdai;
    address comptroller;
    address comp;
    address tack;
    address delegate;
}

// Init a D3M instance
library D3MInit {

    function initCore(
        DssInstance memory dss,
        D3MCoreInstance memory d3mCore
    ) internal {
        D3MHubLike_2 hub = D3MHubLike_2(d3mCore.hub);
        D3MMomLike_2 mom = D3MMomLike_2(d3mCore.mom);

        // Sanity checks
        require(hub.vat() == address(dss.vat), "Hub vat mismatch");
        require(hub.daiJoin() == address(dss.daiJoin), "Hub daiJoin mismatch");

        hub.file("vow", address(dss.vow));
        hub.file("end", address(dss.end));

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

        dss.vat.rely(address(hub));

        dss.chainlog.setAddress("DIRECT_HUB", address(hub));
        dss.chainlog.setAddress("DIRECT_MOM", address(mom));
    }

    function _init(
        DssInstance memory dss,
        D3MInstance memory d3m,
        D3MCommonConfig memory cfg,
        address gem
    ) private {
        bytes32 ilk = cfg.ilk;
        D3MHubLike_2 hub = D3MHubLike_2(cfg.hub);
        D3MOracleLike_2 oracle = D3MOracleLike_2(d3m.oracle);

        // Sanity checks
        require(oracle.vat() == address(dss.vat), "Oracle vat mismatch");
        require(oracle.ilk() == ilk, "Oracle ilk mismatch");

        hub.file(ilk, "pool", d3m.pool);
        hub.file(ilk, "plan", d3m.plan);
        hub.file(ilk, "tau", cfg.tau);

        oracle.file("hub", address(hub));

        dss.spotter.file(ilk, "pip", address(oracle));
        dss.spotter.file(ilk, "mat", 10 ** 27);
        uint256 previousIlkLine;
        if (cfg.existingIlk) {
            (,,, previousIlkLine,) = dss.vat.ilks(ilk);
        } else {
            dss.vat.init(ilk);
            dss.jug.init(ilk);
        }
        dss.vat.file(ilk, "line", cfg.gap);
        dss.vat.file("Line", dss.vat.Line() + cfg.gap - previousIlkLine);
        DssAutoLineAbstract(dss.chainlog.getAddress("MCD_IAM_AUTO_LINE")).setIlk(
            ilk,
            cfg.maxLine,
            cfg.gap,
            cfg.ttl
        );
        dss.spotter.poke(ilk);

        IlkRegistryAbstract(dss.chainlog.getAddress("ILK_REGISTRY")).put(
            ilk,
            address(hub),
            address(gem),
            GemAbstract(gem).decimals(),
            4,
            address(oracle),
            address(0),
            GemAbstract(gem).name(),
            GemAbstract(gem).symbol()
        );

        string memory clPrefix = ScriptTools.ilkToChainlogFormat(ilk);
        dss.chainlog.setAddress(ScriptTools.stringToBytes32(string(abi.encodePacked(clPrefix, "_POOL"))), d3m.pool);
        dss.chainlog.setAddress(ScriptTools.stringToBytes32(string(abi.encodePacked(clPrefix, "_PLAN"))), d3m.plan);
        dss.chainlog.setAddress(ScriptTools.stringToBytes32(string(abi.encodePacked(clPrefix, "_ORACLE"))), d3m.oracle);
    }

    function initAave(
        DssInstance memory dss,
        D3MInstance memory d3m,
        D3MCommonConfig memory cfg,
        D3MAaveConfig memory aaveCfg
    ) internal {
        AavePlanLike plan = AavePlanLike(d3m.plan);
        AavePoolLike pool = AavePoolLike(d3m.pool);
        ADaiLike adai = ADaiLike(aaveCfg.adai);

        _init(dss, d3m, cfg, address(adai));

        // Sanity checks
        require(pool.hub() == cfg.hub, "Pool hub mismatch");
        require(pool.ilk() == cfg.ilk, "Pool ilk mismatch");
        require(pool.vat() == address(dss.vat), "Pool vat mismatch");
        require(pool.dai() == address(dss.dai), "Pool dai mismatch");
        require(pool.adai() == address(adai), "Pool adai mismatch");
        require(pool.stableDebt() == aaveCfg.stableDebt, "Pool stableDebt mismatch");
        require(pool.variableDebt() == aaveCfg.variableDebt, "Pool variableDebt mismatch");

        require(plan.adai() == address(adai), "Plan adai mismatch");
        require(plan.stableDebt() == aaveCfg.stableDebt, "Plan stableDebt mismatch");
        require(plan.variableDebt() == aaveCfg.variableDebt, "Plan variableDebt mismatch");
        require(plan.tack() == aaveCfg.tack, "Plan tack mismatch");
        require(plan.adaiRevision() == aaveCfg.adaiRevision, "Plan adaiRevision mismatch");
        require(adai.ATOKEN_REVISION() == aaveCfg.adaiRevision, "ADai adaiRevision mismatch");

        plan.rely(cfg.mom);
        pool.file("king", aaveCfg.king);
        plan.file("bar", aaveCfg.bar);
    }

    function initCompound(
        DssInstance memory dss,
        D3MInstance memory d3m,
        D3MCommonConfig memory cfg,
        D3MCompoundConfig memory compoundCfg
    ) internal {
        CompoundPlanLike plan = CompoundPlanLike(d3m.plan);
        CompoundPoolLike pool = CompoundPoolLike(d3m.pool);
        CDaiLike cdai = CDaiLike(compoundCfg.cdai);

        _init(dss, d3m, cfg, address(cdai));

        // Sanity checks
        require(pool.hub() == cfg.hub, "Pool hub mismatch");
        require(pool.ilk() == cfg.ilk, "Pool ilk mismatch");
        require(pool.vat() == address(dss.vat), "Pool vat mismatch");
        require(pool.dai() == address(dss.dai), "Pool dai mismatch");
        require(pool.comptroller() == compoundCfg.comptroller, "Pool comptroller mismatch");
        require(pool.comp() == compoundCfg.comp, "Pool comp mismatch");
        require(pool.cDai() == address(cdai), "Pool cDai mismatch");

        require(plan.tack() == compoundCfg.tack, "Plan tack mismatch");
        require(cdai.interestRateModel() == compoundCfg.tack, "CDai tack mismatch");
        require(plan.delegate() == compoundCfg.delegate, "Plan delegate mismatch");
        require(cdai.implementation() == compoundCfg.delegate, "CDai delegate mismatch");
        require(plan.cDai() == address(cdai), "Plan cDai mismatch");

        plan.rely(cfg.mom);
        pool.file("king", compoundCfg.king);
        plan.file("barb", compoundCfg.barb);
    }

}

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

/* pragma solidity 0.8.16; */

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

/* import { MCD } from "dss-test/MCD.sol"; */
/* import { D3MInit, D3MCommonConfig, D3MAaveConfig } from "src/dependencies/dss-direct-deposit/D3MInit.sol"; */
/* import { D3MInstance } from "src/dependencies/dss-direct-deposit/D3MInstance.sol"; */

interface VestLike {
    function restrict(uint256) external;
    function create(address, uint256, uint256, uint256, uint256, address) external returns (uint256);
}

interface GemLike {
    function allowance(address, address) external view returns (uint256);
    function approve(address, uint256) external returns (bool);
}

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/54731a9e15d6da097d578d8050bec900cf7223f5/governance/votes/Executive%20Vote%20-%20February%2022%2C%202023.md -q -O - 2>/dev/null)"
    string public constant override description =
        "2023-02-22 MakerDAO Executive Spell | Hash: 0xa3cbfacc53bcdef9863383b0a0e16bd805fb2cd9df5957a05e0bbe91373fb1b8";

    // Turn office hours on
    function officeHours() public pure override returns (bool) {
        return true;
    }

    // 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 constant ZERO_FIVE_PCT_RATE         = 1000000000158153903837946257;
    uint256 constant ONE_SEVENTY_FIVE_PCT_RATE  = 1000000000550121712943459312;
    uint256 constant THREE_TWENTY_FIVE_PCT_RATE = 1000000001014175731521720677;

    // Tuesday, 1 March 2022 00:00:00 UTC
    uint256 constant public MAR_01_2022 = 1646092800;
    // Saturday, 1 March 2025 00:00:00 UTC
    uint256 constant public MAR_01_2025 = 1740787200;

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

    address internal constant AAVE_D3M_PLAN     = 0x5846Aee09298f8F3aB5D837d540232d19e5d5813;
    address internal constant AAVE_D3M_POOL     = 0x66aE0574Eb28B92c82569b293B856BB99f80F040;
    address internal constant AAVE_D3M_ORACLE   = 0x634051fbA31829E245C616e79E289f89c8B851c2;

    address internal constant AAVE_DAI_STABLE_DEBT       = 0x778A13D3eeb110A4f7bb6529F99c000119a08E92;
    address internal constant AAVE_DAI_VARIABLE_DEBT     = 0x6C3c78838c761c6Ac7bE9F59fe808ea2A6E4379d;
    address internal constant AAVE_DAI_INTEREST_STRATEGY = 0xfffE32106A68aA3eD39CcCE673B646423EEaB62a;

    address internal constant SF_IC_WALLET_0    = 0x31C01e90Edcf8602C1A18B2aE4e5A72D8DCE76bD;
    address internal constant SF_IC_WALLET_1    = 0x12b19C5857CF92AaE5e5e5ADc6350e25e4C902e9;

    GemLike  internal immutable MKR          = GemLike(DssExecLib.mkr());
    VestLike internal immutable MCD_VEST_MKR = VestLike(DssExecLib.getChangelogAddress("MCD_VEST_MKR_TREASURY"));

    function actions() public override {

        // ---- New Aave v2 D3M ----
        // https://vote.makerdao.com/polling/QmUMyywc#poll-detail
        // dss-direct-deposit @ e10d92ed647bfc329c04caf306988bb73ed69640

        D3MInstance memory d3m = D3MInstance({
            plan:   AAVE_D3M_PLAN,
            pool:   AAVE_D3M_POOL,
            oracle: AAVE_D3M_ORACLE
        });

        D3MCommonConfig memory cfg = D3MCommonConfig({
            hub:         DssExecLib.getChangelogAddress("DIRECT_HUB"),
            mom:         DssExecLib.getChangelogAddress("DIRECT_MOM"),
            ilk:         "DIRECT-AAVEV2-DAI",
            existingIlk: true,              // No need to re-init in vat and jug
            maxLine:     5 * MILLION * RAD, // Set line to 5 million DAI
            gap:         5 * MILLION * RAD, // Set gap to 5 million DAI
            ttl:         12 hours,          // Set ttl to 12 hours
            tau:         7 days             // Set tau to 7 days
        });

        D3MAaveConfig memory aaveCfg = D3MAaveConfig({
            king:         DssExecLib.getChangelogAddress("MCD_PAUSE_PROXY"),
            bar:          2 * RAY / 100, // Set bar to 2%
            adai:         DssExecLib.getChangelogAddress("ADAI"),
            stableDebt:   AAVE_DAI_STABLE_DEBT,
            variableDebt: AAVE_DAI_VARIABLE_DEBT,
            tack:         AAVE_DAI_INTEREST_STRATEGY,
            adaiRevision: 2
        });

        D3MInit.initAave({
            dss:     MCD.loadFromChainlog(DssExecLib.LOG),
            d3m:     d3m,
            cfg:     cfg,
            aaveCfg: aaveCfg
        });


        // ---- MOMC Parameter Changes ----
        // https://vote.makerdao.com/polling/QmUMyywc#poll-detail

        // Stability Fee Changes

        //Increase WSTETH-B Stability Fee to 0.5%
        DssExecLib.setIlkStabilityFee("WSTETH-B", ZERO_FIVE_PCT_RATE, true);

        // Reduce RETH-A Stability Fee to 0.5%
        DssExecLib.setIlkStabilityFee("RETH-A", ZERO_FIVE_PCT_RATE, true);

        // Reduce WBTC-A Stability Fee to 1.75%
        DssExecLib.setIlkStabilityFee("WBTC-A", ONE_SEVENTY_FIVE_PCT_RATE, true);

        // Reduce WBTC-B Stability Fee to 3.25%
        DssExecLib.setIlkStabilityFee("WBTC-B", THREE_TWENTY_FIVE_PCT_RATE, true);

        // line changes

        // Increase CRVV1ETHSTETH-A line to 100 million DAI
        DssExecLib.setIlkAutoLineDebtCeiling("CRVV1ETHSTETH-A", 100 * MILLION);

        // Increase RETH-A line to 10 million DAI
        DssExecLib.setIlkAutoLineDebtCeiling("RETH-A", 10 * MILLION);

        // Increase MATIC-A line to 15 million DAI
        DssExecLib.setIlkAutoLineDebtCeiling("MATIC-A", 15 * MILLION);

        // Increase DIRECT-COMPV2-DAI line to 30 million DAI
        DssExecLib.setIlkAutoLineDebtCeiling("DIRECT-COMPV2-DAI", 30 * MILLION);

        // ---- SF-001 Contributor Vesting ----

        // Increase allowance by new vesting delta
        MKR.approve(address(MCD_VEST_MKR), MKR.allowance(address(this), address(MCD_VEST_MKR)) + 435 ether);

        // Restrict: yes | Cliff: 2023-03-01 | 2022-03-01 to 2025-03-01 | 240 MKR | 0x31C01e90Edcf8602C1A18B2aE4e5A72D8DCE76bD
        MCD_VEST_MKR.restrict(
            MCD_VEST_MKR.create(
                SF_IC_WALLET_0,                             // usr
                240 ether,                                  // tot
                MAR_01_2022,                                // bgn
                MAR_01_2025 - MAR_01_2022,                  // tau
                365 days,                                   // eta
                address(0)                                  // mgr
            )
        );

        // Restrict: yes | Cliff: 2023-03-01 | 2022-03-01 to 2025-03-01 | 195 MKR | 0x12b19C5857CF92AaE5e5e5ADc6350e25e4C902e9
        MCD_VEST_MKR.restrict(
            MCD_VEST_MKR.create(
                SF_IC_WALLET_1,                             // usr
                195 ether,                                  // tot
                MAR_01_2022,                                // bgn
                MAR_01_2025 - MAR_01_2022,                  // tau
                365 days,                                   // eta
                address(0)                                  // mgr
            )
        );

        // Bump changelog
        DssExecLib.setChangelogVersion("1.14.9");
    }
}

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

Contract Security Audit

Contract ABI

[{"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"}]

6101006040523480156200001257600080fd5b5062278d004262000024919062000247565b604051620000329062000200565b604051809103906000f0801580156200004f573d6000803e3d6000fd5b5073da0ab1e0017debcd72be8599041a2aa3ba7e740f73ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b81526004016200009d90620002a8565b602060405180830381865afa158015620000bb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000e191906200032d565b73ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff16815250508160c081815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250506040516024016040516020818303038152906040527f61461954000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060019081620001e39190620005cf565b50600080829050803f9150816080818152505050505050620006b6565b61511d806200194683390190565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000254826200020e565b915062000261836200020e565b92508282019050808211156200027c576200027b62000218565b5b92915050565b7f4d43445f50415553450000000000000000000000000000000000000000000000815250565b6000602082019050620002be6000830162000282565b919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620002f582620002c8565b9050919050565b6200030781620002e8565b81146200031357600080fd5b50565b6000815190506200032781620002fc565b92915050565b600060208284031215620003465762000345620002c3565b5b6000620003568482850162000316565b91505092915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620003e157607f821691505b602082108103620003f757620003f662000399565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620004617fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000422565b6200046d868362000422565b95508019841693508086168417925050509392505050565b6000819050919050565b6000620004b0620004aa620004a4846200020e565b62000485565b6200020e565b9050919050565b6000819050919050565b620004cc836200048f565b620004e4620004db82620004b7565b8484546200042f565b825550505050565b600090565b620004fb620004ec565b62000508818484620004c1565b505050565b5b81811015620005305762000524600082620004f1565b6001810190506200050e565b5050565b601f8211156200057f576200054981620003fd565b620005548462000412565b8101602085101562000564578190505b6200057c620005738562000412565b8301826200050d565b50505b505050565b600082821c905092915050565b6000620005a46000198460080262000584565b1980831691505092915050565b6000620005bf838362000591565b9150826002028217905092915050565b620005da826200035f565b67ffffffffffffffff811115620005f657620005f56200036a565b5b620006028254620003c8565b6200060f82828562000534565b600060209050601f83116001811462000647576000841562000632578287015190505b6200063e8582620005b1565b865550620006ae565b601f1984166200065786620003fd565b60005b8281101562000681578489015182556001820191506020850194506020810190506200065a565b86831015620006a157848901516200069d601f89168262000591565b8355505b6001600288020188555050505b505050505050565b60805160a05160c05160e0516112096200073d6000396000818161047601528181610505015281816106ac015261074c0152600081816102e501526106050152600081816102c101528181610347015281816103dd0152818161054101528181610788015261082a0152600081816103210152818161056201526107a901526112096000f3fe608060405234801561001057600080fd5b50600436106100ce5760003560e01c80637284e4161161008c578063ae8421e111610066578063ae8421e1146101cd578063b0604a26146101eb578063f7992d85146101f5578063fe7d47bb14610213576100ce565b80637284e416146101875780638456cb59146101a557806396d373e5146101c3576100ce565b8062a7029b146100d35780630a7a1c4d146100f15780634665096d1461010f57806351973ec91461012d57806351f910661461014b5780636e832f0714610169575b600080fd5b6100db610231565b6040516100e89190610959565b60405180910390f35b6100f96102bf565b60405161010691906109bc565b60405180910390f35b6101176102e3565b60405161012491906109f0565b60405180910390f35b610135610307565b6040516101429190610a6a565b60405180910390f35b61015361031f565b6040516101609190610a9e565b60405180910390f35b610171610343565b60405161017e9190610ad4565b60405180910390f35b61018f6103d9565b60405161019c9190610b44565b60405180910390f35b6101ad610474565b6040516101ba9190610b87565b60405180910390f35b6101cb610498565b005b6101d56105f0565b6040516101e29190610ad4565b60405180910390f35b6101f3610603565b005b6101fd610820565b60405161020a91906109f0565b60405180910390f35b61021b610826565b60405161022891906109f0565b60405180910390f35b6001805461023e90610bd1565b80601f016020809104026020016040519081016040528092919081815260200182805461026a90610bd1565b80156102b75780601f1061028c576101008083540402835291602001916102b7565b820191906000526020600020905b81548152906001019060200180831161029a57829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b73da0ab1e0017debcd72be8599041a2aa3ba7e740f81565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e832f076040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d49190610c42565b905090565b60607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637284e4166040518163ffffffff1660e01b8152600401600060405180830381865afa158015610446573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061046f9190610d95565b905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b600260009054906101000a900460ff16156104e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104df90610e2a565b60405180910390fd5b6001600260006101000a81548160ff0219169083151502179055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663168ccd677f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060016000546040518563ffffffff1660e01b81526004016105a59493929190610ee3565b6000604051808303816000875af11580156105c4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906105ed9190610fd0565b50565b600260009054906101000a900460ff1681565b7f0000000000000000000000000000000000000000000000000000000000000000421115610666576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065d90611065565b60405180910390fd5b60008054146106aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a1906110f7565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636a42b8f86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610715573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107399190611143565b42610744919061119f565b6000819055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346d2fbbb7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060016000546040518563ffffffff1660e01b81526004016107ec9493929190610ee3565b600060405180830381600087803b15801561080657600080fd5b505af115801561081a573d6000803e3d6000fd5b50505050565b60005481565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663bf0fbcec6000546040518263ffffffff1660e01b815260040161088391906109f0565b602060405180830381865afa1580156108a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c49190611143565b905090565b600081519050919050565b600082825260208201905092915050565b60005b838110156109035780820151818401526020810190506108e8565b60008484015250505050565b6000601f19601f8301169050919050565b600061092b826108c9565b61093581856108d4565b93506109458185602086016108e5565b61094e8161090f565b840191505092915050565b600060208201905081810360008301526109738184610920565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006109a68261097b565b9050919050565b6109b68161099b565b82525050565b60006020820190506109d160008301846109ad565b92915050565b6000819050919050565b6109ea816109d7565b82525050565b6000602082019050610a0560008301846109e1565b92915050565b6000819050919050565b6000610a30610a2b610a268461097b565b610a0b565b61097b565b9050919050565b6000610a4282610a15565b9050919050565b6000610a5482610a37565b9050919050565b610a6481610a49565b82525050565b6000602082019050610a7f6000830184610a5b565b92915050565b6000819050919050565b610a9881610a85565b82525050565b6000602082019050610ab36000830184610a8f565b92915050565b60008115159050919050565b610ace81610ab9565b82525050565b6000602082019050610ae96000830184610ac5565b92915050565b600081519050919050565b600082825260208201905092915050565b6000610b1682610aef565b610b208185610afa565b9350610b308185602086016108e5565b610b398161090f565b840191505092915050565b60006020820190508181036000830152610b5e8184610b0b565b905092915050565b6000610b7182610a37565b9050919050565b610b8181610b66565b82525050565b6000602082019050610b9c6000830184610b78565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680610be957607f821691505b602082108103610bfc57610bfb610ba2565b5b50919050565b6000604051905090565b600080fd5b600080fd5b610c1f81610ab9565b8114610c2a57600080fd5b50565b600081519050610c3c81610c16565b92915050565b600060208284031215610c5857610c57610c0c565b5b6000610c6684828501610c2d565b91505092915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610cb18261090f565b810181811067ffffffffffffffff82111715610cd057610ccf610c79565b5b80604052505050565b6000610ce3610c02565b9050610cef8282610ca8565b919050565b600067ffffffffffffffff821115610d0f57610d0e610c79565b5b610d188261090f565b9050602081019050919050565b6000610d38610d3384610cf4565b610cd9565b905082815260208101848484011115610d5457610d53610c74565b5b610d5f8482856108e5565b509392505050565b600082601f830112610d7c57610d7b610c6f565b5b8151610d8c848260208601610d25565b91505092915050565b600060208284031215610dab57610daa610c0c565b5b600082015167ffffffffffffffff811115610dc957610dc8610c11565b5b610dd584828501610d67565b91505092915050565b7f7370656c6c2d616c72656164792d636173740000000000000000000000000000600082015250565b6000610e14601283610afa565b9150610e1f82610dde565b602082019050919050565b60006020820190508181036000830152610e4381610e07565b9050919050565b60008190508160005260206000209050919050565b60008154610e6c81610bd1565b610e7681866108d4565b94506001821660008114610e915760018114610ea757610eda565b60ff198316865281151560200286019350610eda565b610eb085610e4a565b60005b83811015610ed257815481890152600182019150602081019050610eb3565b808801955050505b50505092915050565b6000608082019050610ef860008301876109ad565b610f056020830186610a8f565b8181036040830152610f178185610e5f565b9050610f2660608301846109e1565b95945050505050565b600067ffffffffffffffff821115610f4a57610f49610c79565b5b610f538261090f565b9050602081019050919050565b6000610f73610f6e84610f2f565b610cd9565b905082815260208101848484011115610f8f57610f8e610c74565b5b610f9a8482856108e5565b509392505050565b600082601f830112610fb757610fb6610c6f565b5b8151610fc7848260208601610f60565b91505092915050565b600060208284031215610fe657610fe5610c0c565b5b600082015167ffffffffffffffff81111561100457611003610c11565b5b61101084828501610fa2565b91505092915050565b7f5468697320636f6e747261637420686173206578706972656400000000000000600082015250565b600061104f601983610afa565b915061105a82611019565b602082019050919050565b6000602082019050818103600083015261107e81611042565b9050919050565b7f54686973207370656c6c2068617320616c7265616479206265656e207363686560008201527f64756c6564000000000000000000000000000000000000000000000000000000602082015250565b60006110e1602583610afa565b91506110ec82611085565b604082019050919050565b60006020820190508181036000830152611110816110d4565b9050919050565b611120816109d7565b811461112b57600080fd5b50565b60008151905061113d81611117565b92915050565b60006020828403121561115957611158610c0c565b5b60006111678482850161112e565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006111aa826109d7565b91506111b5836109d7565b92508282019050808211156111cd576111cc611170565b5b9291505056fea2646970667358221220835bf7694324cdc34d1734d769aec464b6ce171c2d4ee21227eb2ad323876a9f64736f6c6343000810003360c0604052738de6ddbcd5053d32292aaa0d2105a32d108484a6637e992cb86040518163ffffffff1660e01b8152600401602060405180830381865af41580156200004e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000749190620001d1565b73ffffffffffffffffffffffffffffffffffffffff1660809073ffffffffffffffffffffffffffffffffffffffff16815250738de6ddbcd5053d32292aaa0d2105a32d108484a663a16ed56f6040518163ffffffff1660e01b8152600401620000dd9062000229565b602060405180830381865af4158015620000fb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001219190620001d1565b73ffffffffffffffffffffffffffffffffffffffff1660a09073ffffffffffffffffffffffffffffffffffffffff168152503480156200016057600080fd5b5062000244565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062000199826200016c565b9050919050565b620001ab816200018c565b8114620001b757600080fd5b50565b600081519050620001cb81620001a0565b92915050565b600060208284031215620001ea57620001e962000167565b5b6000620001fa84828501620001ba565b91505092915050565b7f4d43445f564553545f4d4b525f54524541535552590000000000000000000000815250565b60006020820190506200023f6000830162000203565b919050565b60805160a051614e896200029460003960008181610b5601528181610bbe01528181610ca801528181610ce401528181610e0d0152610e49015260008181610b1a0152610b810152614e896000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80637284e4161161005b5780637284e416146100c857806383c27ea4146100e6578063bf0fbcec14610104578063f99e36bc146101345761007d565b80636146195414610082578063630fd5b91461008c5780636e832f07146100aa575b600080fd5b61008a61013e565b005b610094610208565b6040516100a19190613256565b60405180910390f35b6100b2610210565b6040516100bf919061328c565b60405180910390f35b6100d0610219565b6040516100dd9190613337565b60405180910390f35b6100ee610235565b6040516100fb9190613256565b60405180910390f35b61011e60048036038101906101199190613399565b61023d565b60405161012b9190613256565b60405180910390f35b61013c6102dd565b005b738de6ddbcd5053d32292aaa0d2105a32d108484a66335329d4c42610161610210565b6040518363ffffffff1660e01b815260040161017e9291906133f5565b602060405180830381865af415801561019b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101bf919061344a565b6101fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101f5906134c3565b60405180910390fd5b6102066102dd565b565b6367c24e0081565b60006001905090565b6040518060a00160405280606e8152602001614de6606e913981565b63621d620081565b600064ffffffffff801682111561025357600080fd5b738de6ddbcd5053d32292aaa0d2105a32d108484a663d25574568342610277610210565b6040518463ffffffff1660e01b8152600401610295939291906134e3565b602060405180830381865af41580156102b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d6919061352f565b9050919050565b60006040518060600160405280735846aee09298f8f3ab5d837d540232d19e5d581373ffffffffffffffffffffffffffffffffffffffff1681526020017366ae0574eb28b92c82569b293b856bb99f80f04073ffffffffffffffffffffffffffffffffffffffff16815260200173634051fba31829e245c616e79e289f89c8b851c273ffffffffffffffffffffffffffffffffffffffff1681525090506000604051806101000160405280738de6ddbcd5053d32292aaa0d2105a32d108484a663a16ed56f6040518163ffffffff1660e01b81526004016103bd90613582565b602060405180830381865af41580156103da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103fe91906135f9565b73ffffffffffffffffffffffffffffffffffffffff168152602001738de6ddbcd5053d32292aaa0d2105a32d108484a663a16ed56f6040518163ffffffff1660e01b815260040161044e9061364c565b602060405180830381865af415801561046b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048f91906135f9565b73ffffffffffffffffffffffffffffffffffffffff1681526020017f4449524543542d4141564556322d4441490000000000000000000000000000008152602001600115158152602001722cd76fe086b93ce2f768a00b22a00000000000620f424060056104fd9190613694565b6105079190613694565b8152602001722cd76fe086b93ce2f768a00b22a00000000000620f424060056105309190613694565b61053a9190613694565b815260200161a8c0815260200162093a80815250905060006040518060e00160405280738de6ddbcd5053d32292aaa0d2105a32d108484a663a16ed56f6040518163ffffffff1660e01b815260040161059290613714565b602060405180830381865af41580156105af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d391906135f9565b73ffffffffffffffffffffffffffffffffffffffff16815260200160646b033b2e3c9fd0803ce800000060026106099190613694565b610613919061375c565b8152602001738de6ddbcd5053d32292aaa0d2105a32d108484a663a16ed56f6040518163ffffffff1660e01b815260040161064d906137b3565b602060405180830381865af415801561066a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068e91906135f9565b73ffffffffffffffffffffffffffffffffffffffff16815260200173778a13d3eeb110a4f7bb6529f99c000119a08e9273ffffffffffffffffffffffffffffffffffffffff168152602001736c3c78838c761c6ac7be9f59fe808ea2a6e4379d73ffffffffffffffffffffffffffffffffffffffff16815260200173fffe32106a68aa3ed39ccce673b646423eeab62a73ffffffffffffffffffffffffffffffffffffffff1681526020016002815250905061076861076073da0ab1e0017debcd72be8599041a2aa3ba7e740f610fda565b848484610ff2565b738de6ddbcd5053d32292aaa0d2105a32d108484a663e40898e06b033b2e3ca2026060221a219160016040518363ffffffff1660e01b81526004016107ae929190613801565b60006040518083038186803b1580156107c657600080fd5b505af41580156107da573d6000803e3d6000fd5b50505050738de6ddbcd5053d32292aaa0d2105a32d108484a663e40898e06b033b2e3ca2026060221a219160016040518363ffffffff1660e01b815260040161082492919061385c565b60006040518083038186803b15801561083c57600080fd5b505af4158015610850573d6000803e3d6000fd5b50505050738de6ddbcd5053d32292aaa0d2105a32d108484a663e40898e06b033b2e3ca772ed056b396bf060016040518363ffffffff1660e01b815260040161089a9291906138b7565b60006040518083038186803b1580156108b257600080fd5b505af41580156108c6573d6000803e3d6000fd5b50505050738de6ddbcd5053d32292aaa0d2105a32d108484a663e40898e06b033b2e3cade393b1412c916560016040518363ffffffff1660e01b8152600401610910929190613912565b60006040518083038186803b15801561092857600080fd5b505af415801561093c573d6000803e3d6000fd5b50505050738de6ddbcd5053d32292aaa0d2105a32d108484a66327eddd12620f4240606461096a9190613694565b6040518263ffffffff1660e01b8152600401610986919061396d565b60006040518083038186803b15801561099e57600080fd5b505af41580156109b2573d6000803e3d6000fd5b50505050738de6ddbcd5053d32292aaa0d2105a32d108484a66327eddd12620f4240600a6109e09190613694565b6040518263ffffffff1660e01b81526004016109fc9190613994565b60006040518083038186803b158015610a1457600080fd5b505af4158015610a28573d6000803e3d6000fd5b50505050738de6ddbcd5053d32292aaa0d2105a32d108484a66327eddd12620f4240600f610a569190613694565b6040518263ffffffff1660e01b8152600401610a7291906139e1565b60006040518083038186803b158015610a8a57600080fd5b505af4158015610a9e573d6000803e3d6000fd5b50505050738de6ddbcd5053d32292aaa0d2105a32d108484a66327eddd12620f4240601e610acc9190613694565b6040518263ffffffff1660e01b8152600401610ae89190613a2e565b60006040518083038186803b158015610b0057600080fd5b505af4158015610b14573d6000803e3d6000fd5b505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663095ea7b37f0000000000000000000000000000000000000000000000000000000000000000681794d673456eec00007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e307f00000000000000000000000000000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401610bfa929190613a64565b602060405180830381865afa158015610c17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3b919061352f565b610c459190613a8d565b6040518363ffffffff1660e01b8152600401610c62929190613ac1565b6020604051808303816000875af1158015610c81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca5919061344a565b507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633c433d5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663db64ff8f7331c01e90edcf8602c1a18b2ae4e5a72d8dce76bd680d02ab486cedc0000063621d6200806367c24e00610d529190613aea565b6301e1338060006040518763ffffffff1660e01b8152600401610d7a96959493929190613b9e565b6020604051808303816000875af1158015610d99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbd919061352f565b6040518263ffffffff1660e01b8152600401610dd99190613256565b600060405180830381600087803b158015610df357600080fd5b505af1158015610e07573d6000803e3d6000fd5b505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633c433d5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663db64ff8f7312b19c5857cf92aae5e5e5adc6350e25e4c902e9680a922b2ad8812c000063621d6200806367c24e00610eb79190613aea565b6301e1338060006040518763ffffffff1660e01b8152600401610edf96959493929190613c3a565b6020604051808303816000875af1158015610efe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f22919061352f565b6040518263ffffffff1660e01b8152600401610f3e9190613256565b600060405180830381600087803b158015610f5857600080fd5b505af1158015610f6c573d6000803e3d6000fd5b50505050738de6ddbcd5053d32292aaa0d2105a32d108484a6635f3a7dd76040518163ffffffff1660e01b8152600401610fa590613cf8565b60006040518083038186803b158015610fbd57600080fd5b505af4158015610fd1573d6000803e3d6000fd5b50505050505050565b610fe261309a565b610feb82611c43565b9050919050565b6000836000015190506000846020015190506000836040015190506110198787878461217b565b846000015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1663365a86fc6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561107f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a391906135f9565b73ffffffffffffffffffffffffffffffffffffffff16146110f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f090613d64565b60405180910390fd5b84604001518273ffffffffffffffffffffffffffffffffffffffff1663c5ce281e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d9190613dba565b146111ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111a490613e33565b60405180910390fd5b866020015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff166336569e776040518163ffffffff1660e01b8152600401602060405180830381865afa158015611213573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123791906135f9565b73ffffffffffffffffffffffffffffffffffffffff161461128d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128490613e9f565b60405180910390fd5b866060015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1663f4b9fa756040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131791906135f9565b73ffffffffffffffffffffffffffffffffffffffff161461136d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161136490613f0b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1663f32d68466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f391906135f9565b73ffffffffffffffffffffffffffffffffffffffff1614611449576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161144090613f77565b60405180910390fd5b836060015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff166353ab6f436040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d391906135f9565b73ffffffffffffffffffffffffffffffffffffffff1614611529576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161152090613fe3565b60405180910390fd5b836080015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1663ff58c21c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561158f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115b391906135f9565b73ffffffffffffffffffffffffffffffffffffffff1614611609576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116009061404f565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1663f32d68466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561166b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061168f91906135f9565b73ffffffffffffffffffffffffffffffffffffffff16146116e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116dc906140bb565b60405180910390fd5b836060015173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff166353ab6f436040518163ffffffff1660e01b8152600401602060405180830381865afa15801561174b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176f91906135f9565b73ffffffffffffffffffffffffffffffffffffffff16146117c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117bc90614127565b60405180910390fd5b836080015173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1663ff58c21c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561182b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061184f91906135f9565b73ffffffffffffffffffffffffffffffffffffffff16146118a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161189c90614193565b60405180910390fd5b8360a0015173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1663873f4cca6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561190b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061192f91906135f9565b73ffffffffffffffffffffffffffffffffffffffff1614611985576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197c906141ff565b60405180910390fd5b8360c001518373ffffffffffffffffffffffffffffffffffffffff16638f1296bf6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f9919061352f565b14611a39576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a309061426b565b60405180910390fd5b8360c001518173ffffffffffffffffffffffffffffffffffffffff16630bd7ad3b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aad919061352f565b14611aed576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ae4906142d7565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff166365fae35e86602001516040518263ffffffff1660e01b8152600401611b2a91906142f7565b600060405180830381600087803b158015611b4457600080fd5b505af1158015611b58573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663d4e8be8385600001516040518263ffffffff1660e01b8152600401611b999190614338565b600060405180830381600087803b158015611bb357600080fd5b505af1158015611bc7573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff166329ae811485602001516040518263ffffffff1660e01b8152600401611c089190614385565b600060405180830381600087803b158015611c2257600080fd5b505af1158015611c36573d6000803e3d6000fd5b5050505050505050505050565b611c4b61309a565b81816000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611cad817f4d43445f56415400000000000000000000000000000000000000000000000000612e63565b816020019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611d0e817f4d43445f4a4f494e5f4441490000000000000000000000000000000000000000612e63565b816040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611d6f817f4d43445f44414900000000000000000000000000000000000000000000000000612e63565b816060019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611dd0817f4d43445f564f5700000000000000000000000000000000000000000000000000612e63565b816080019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611e31817f4d43445f444f4700000000000000000000000000000000000000000000000000612e63565b8160a0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611e92817f4d43445f504f5400000000000000000000000000000000000000000000000000612e63565b8160c0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611ef3817f4d43445f4a554700000000000000000000000000000000000000000000000000612e63565b8160e0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611f54817f4d43445f53504f54000000000000000000000000000000000000000000000000612e63565b81610100019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611fb6817f4d43445f454e4400000000000000000000000000000000000000000000000000612e63565b81610120019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050612018817f4d43445f43555245000000000000000000000000000000000000000000000000612e63565b81610140019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061207a817f4d43445f464c4150000000000000000000000000000000000000000000000000612e63565b81610160019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506120dc817f4d43445f464c4f50000000000000000000000000000000000000000000000000612e63565b81610180019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061213e817f4d43445f45534d00000000000000000000000000000000000000000000000000612e63565b816101a0019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050919050565b600082604001519050600083600001519050600085604001519050866020015173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff166336569e776040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061222091906135f9565b73ffffffffffffffffffffffffffffffffffffffff1614612276576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161226d906143f8565b60405180910390fd5b828173ffffffffffffffffffffffffffffffffffffffff1663c5ce281e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e69190613dba565b14612326576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161231d90614464565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff1663ebecb39d8488602001516040518363ffffffff1660e01b81526004016123659291906144b9565b600060405180830381600087803b15801561237f57600080fd5b505af1158015612393573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff1663ebecb39d8488600001516040518363ffffffff1660e01b81526004016123d6929190614514565b600060405180830381600087803b1580156123f057600080fd5b505af1158015612404573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff16631a0b287e848760e001516040518363ffffffff1660e01b815260040161244792919061456f565b600060405180830381600087803b15801561246157600080fd5b505af1158015612475573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff1663d4e8be83836040518263ffffffff1660e01b81526004016124b291906145ca565b600060405180830381600087803b1580156124cc57600080fd5b505af11580156124e0573d6000803e3d6000fd5b5050505086610100015173ffffffffffffffffffffffffffffffffffffffff1663ebecb39d84836040518363ffffffff1660e01b8152600401612524929190614617565b600060405180830381600087803b15801561253e57600080fd5b505af1158015612552573d6000803e3d6000fd5b5050505086610100015173ffffffffffffffffffffffffffffffffffffffff16631a0b287e846b033b2e3c9fd0803ce80000006040518363ffffffff1660e01b81526004016125a29291906146ad565b600060405180830381600087803b1580156125bc57600080fd5b505af11580156125d0573d6000803e3d6000fd5b50505050600085606001511561267457876020015173ffffffffffffffffffffffffffffffffffffffff1663d9638d36856040518263ffffffff1660e01b815260040161261d91906146e2565b60a060405180830381865afa15801561263a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061265e91906146fd565b9091929350909192509091505080915050612753565b876020015173ffffffffffffffffffffffffffffffffffffffff16633b663195856040518263ffffffff1660e01b81526004016126b191906146e2565b600060405180830381600087803b1580156126cb57600080fd5b505af11580156126df573d6000803e3d6000fd5b505050508760e0015173ffffffffffffffffffffffffffffffffffffffff16633b663195856040518263ffffffff1660e01b815260040161272091906146e2565b600060405180830381600087803b15801561273a57600080fd5b505af115801561274e573d6000803e3d6000fd5b505050505b876020015173ffffffffffffffffffffffffffffffffffffffff16631a0b287e858860a001516040518363ffffffff1660e01b815260040161279692919061479e565b600060405180830381600087803b1580156127b057600080fd5b505af11580156127c4573d6000803e3d6000fd5b50505050876020015173ffffffffffffffffffffffffffffffffffffffff166329ae8114828860a001518b6020015173ffffffffffffffffffffffffffffffffffffffff1663babe8a3f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561283d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612861919061352f565b61286b9190613a8d565b6128759190613aea565b6040518263ffffffff1660e01b815260040161289191906147f9565b600060405180830381600087803b1580156128ab57600080fd5b505af11580156128bf573d6000803e3d6000fd5b50505050876000015173ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b81526004016128fe90614846565b602060405180830381865afa15801561291b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061293f91906135f9565b73ffffffffffffffffffffffffffffffffffffffff16632a48322d8588608001518960a001518a60c001516040518563ffffffff1660e01b8152600401612989949392919061485f565b600060405180830381600087803b1580156129a357600080fd5b505af11580156129b7573d6000803e3d6000fd5b5050505087610100015173ffffffffffffffffffffffffffffffffffffffff16631504460f856040518263ffffffff1660e01b81526004016129f991906146e2565b600060405180830381600087803b158015612a1357600080fd5b505af1158015612a27573d6000803e3d6000fd5b50505050876000015173ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401612a66906148ca565b602060405180830381865afa158015612a83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aa791906135f9565b73ffffffffffffffffffffffffffffffffffffffff16634d8835e68585888973ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b34919061491c565b60048860008d73ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015612b84573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612bad9190614a6f565b8e73ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015612bf8573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190612c219190614a6f565b6040518a63ffffffff1660e01b8152600401612c4599989796959493929190614b24565b600060405180830381600087803b158015612c5f57600080fd5b505af1158015612c73573d6000803e3d6000fd5b505050506000612c8285612ef4565b9050886000015173ffffffffffffffffffffffffffffffffffffffff1663ca446dd9612ccc83604051602001612cb89190614c47565b604051602081830303815290604052613071565b8a602001516040518363ffffffff1660e01b8152600401612cee929190614c69565b600060405180830381600087803b158015612d0857600080fd5b505af1158015612d1c573d6000803e3d6000fd5b50505050886000015173ffffffffffffffffffffffffffffffffffffffff1663ca446dd9612d6883604051602001612d549190614cde565b604051602081830303815290604052613071565b8a600001516040518363ffffffff1660e01b8152600401612d8a929190614c69565b600060405180830381600087803b158015612da457600080fd5b505af1158015612db8573d6000803e3d6000fd5b50505050886000015173ffffffffffffffffffffffffffffffffffffffff1663ca446dd9612e0483604051602001612df09190614d4c565b604051602081830303815290604052613071565b8a604001516040518363ffffffff1660e01b8152600401612e26929190614c69565b600060405180830381600087803b158015612e4057600080fd5b505af1158015612e54573d6000803e3d6000fd5b50505050505050505050505050565b6000826000015173ffffffffffffffffffffffffffffffffffffffff166321f8a721836040518263ffffffff1660e01b8152600401612ea291906146e2565b602060405180830381865afa925050508015612edc57506040513d601f19601f82011682018060405250810190612ed991906135f9565b60015b612ee95760009050612eee565b809150505b92915050565b606060005b6020811015612f3a576000838260208110612f1757612f16614d6e565b5b1a60f81b60f81c60ff160315612f3a578080612f3290614d9d565b915050612ef9565b60008167ffffffffffffffff811115612f5657612f55614953565b5b6040519080825280601f01601f191660200182016040528015612f885781602001600182028036833780820191505090505b50905060005b82811015613066576000858260208110612fab57612faa614d6e565b5b1a60f81b60f81c9050602d8160ff160361300b57605f60f81b838381518110612fd757612fd6614d6e565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350613052565b8060f81b83838151811061302257613021614d6e565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053505b50808061305e90614d9d565b915050612f8e565b508092505050919050565b600080829050600081510361308c576000801b915050613095565b60208301519150505b919050565b604051806101c00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b6000819050919050565b6132508161323d565b82525050565b600060208201905061326b6000830184613247565b92915050565b60008115159050919050565b61328681613271565b82525050565b60006020820190506132a1600083018461327d565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156132e15780820151818401526020810190506132c6565b60008484015250505050565b6000601f19601f8301169050919050565b6000613309826132a7565b61331381856132b2565b93506133238185602086016132c3565b61332c816132ed565b840191505092915050565b6000602082019050818103600083015261335181846132fe565b905092915050565b6000604051905090565b600080fd5b600080fd5b6133768161323d565b811461338157600080fd5b50565b6000813590506133938161336d565b92915050565b6000602082840312156133af576133ae613363565b5b60006133bd84828501613384565b91505092915050565b600064ffffffffff82169050919050565b6133e0816133c6565b82525050565b6133ef81613271565b82525050565b600060408201905061340a60008301856133d7565b61341760208301846133e6565b9392505050565b61342781613271565b811461343257600080fd5b50565b6000815190506134448161341e565b92915050565b6000602082840312156134605761345f613363565b5b600061346e84828501613435565b91505092915050565b7f4f757473696465206f666669636520686f757273000000000000000000000000600082015250565b60006134ad6014836132b2565b91506134b882613477565b602082019050919050565b600060208201905081810360008301526134dc816134a0565b9050919050565b60006060820190506134f860008301866133d7565b61350560208301856133d7565b61351260408301846133e6565b949350505050565b6000815190506135298161336d565b92915050565b60006020828403121561354557613544613363565b5b60006135538482850161351a565b91505092915050565b7f4449524543545f48554200000000000000000000000000000000000000000000815250565b60006020820190506135966000830161355c565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006135c68261359b565b9050919050565b6135d6816135bb565b81146135e157600080fd5b50565b6000815190506135f3816135cd565b92915050565b60006020828403121561360f5761360e613363565b5b600061361d848285016135e4565b91505092915050565b7f4449524543545f4d4f4d00000000000000000000000000000000000000000000815250565b600060208201905061366060008301613626565b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061369f8261323d565b91506136aa8361323d565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156136e3576136e2613665565b5b828202905092915050565b7f4d43445f50415553455f50524f58590000000000000000000000000000000000815250565b6000602082019050613728600083016136ee565b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006137678261323d565b91506137728361323d565b9250826137825761378161372d565b5b828204905092915050565b7f4144414900000000000000000000000000000000000000000000000000000000815250565b60006020820190506137c76000830161378d565b919050565b7f5753544554482d42000000000000000000000000000000000000000000000000815250565b6137fb8161323d565b82525050565b6000606082019050613815600083016137cc565b61382260208301856137f2565b61382f60408301846133e6565b9392505050565b7f524554482d410000000000000000000000000000000000000000000000000000815250565b600060608201905061387060008301613836565b61387d60208301856137f2565b61388a60408301846133e6565b9392505050565b7f574254432d410000000000000000000000000000000000000000000000000000815250565b60006060820190506138cb60008301613891565b6138d860208301856137f2565b6138e560408301846133e6565b9392505050565b7f574254432d420000000000000000000000000000000000000000000000000000815250565b6000606082019050613926600083016138ec565b61393360208301856137f2565b61394060408301846133e6565b9392505050565b7f435256563145544853544554482d410000000000000000000000000000000000815250565b600060408201905061398160008301613947565b61398e60208301846137f2565b92915050565b60006040820190506139a860008301613836565b6139b560208301846137f2565b92915050565b7f4d415449432d4100000000000000000000000000000000000000000000000000815250565b60006040820190506139f5600083016139bb565b613a0260208301846137f2565b92915050565b7f4449524543542d434f4d5056322d444149000000000000000000000000000000815250565b6000604082019050613a4260008301613a08565b613a4f60208301846137f2565b92915050565b613a5e816135bb565b82525050565b6000604082019050613a796000830185613a55565b613a866020830184613a55565b9392505050565b6000613a988261323d565b9150613aa38361323d565b9250828201905080821115613abb57613aba613665565b5b92915050565b6000604082019050613ad66000830185613a55565b613ae36020830184613247565b9392505050565b6000613af58261323d565b9150613b008361323d565b9250828203905081811115613b1857613b17613665565b5b92915050565b6000819050919050565b6000819050919050565b6000613b4d613b48613b4384613b1e565b613b28565b61323d565b9050919050565b613b5d81613b32565b82525050565b6000819050919050565b6000613b88613b83613b7e84613b63565b613b28565b61323d565b9050919050565b613b9881613b6d565b82525050565b600060c082019050613bb36000830189613a55565b613bc06020830188613b54565b613bcd6040830187613247565b613bda6060830186613247565b613be76080830185613b8f565b613bf460a0830184613a55565b979650505050505050565b6000819050919050565b6000613c24613c1f613c1a84613bff565b613b28565b61323d565b9050919050565b613c3481613c09565b82525050565b600060c082019050613c4f6000830189613a55565b613c5c6020830188613c2b565b613c696040830187613247565b613c766060830186613247565b613c836080830185613b8f565b613c9060a0830184613a55565b979650505050505050565b600082825260208201905092915050565b7f312e31342e390000000000000000000000000000000000000000000000000000600082015250565b6000613ce2600683613c9b565b9150613ced82613cac565b602082019050919050565b60006020820190508181036000830152613d1181613cd5565b9050919050565b7f506f6f6c20687562206d69736d61746368000000000000000000000000000000600082015250565b6000613d4e6011836132b2565b9150613d5982613d18565b602082019050919050565b60006020820190508181036000830152613d7d81613d41565b9050919050565b6000819050919050565b613d9781613d84565b8114613da257600080fd5b50565b600081519050613db481613d8e565b92915050565b600060208284031215613dd057613dcf613363565b5b6000613dde84828501613da5565b91505092915050565b7f506f6f6c20696c6b206d69736d61746368000000000000000000000000000000600082015250565b6000613e1d6011836132b2565b9150613e2882613de7565b602082019050919050565b60006020820190508181036000830152613e4c81613e10565b9050919050565b7f506f6f6c20766174206d69736d61746368000000000000000000000000000000600082015250565b6000613e896011836132b2565b9150613e9482613e53565b602082019050919050565b60006020820190508181036000830152613eb881613e7c565b9050919050565b7f506f6f6c20646169206d69736d61746368000000000000000000000000000000600082015250565b6000613ef56011836132b2565b9150613f0082613ebf565b602082019050919050565b60006020820190508181036000830152613f2481613ee8565b9050919050565b7f506f6f6c2061646169206d69736d617463680000000000000000000000000000600082015250565b6000613f616012836132b2565b9150613f6c82613f2b565b602082019050919050565b60006020820190508181036000830152613f9081613f54565b9050919050565b7f506f6f6c20737461626c6544656274206d69736d617463680000000000000000600082015250565b6000613fcd6018836132b2565b9150613fd882613f97565b602082019050919050565b60006020820190508181036000830152613ffc81613fc0565b9050919050565b7f506f6f6c207661726961626c6544656274206d69736d61746368000000000000600082015250565b6000614039601a836132b2565b915061404482614003565b602082019050919050565b600060208201905081810360008301526140688161402c565b9050919050565b7f506c616e2061646169206d69736d617463680000000000000000000000000000600082015250565b60006140a56012836132b2565b91506140b08261406f565b602082019050919050565b600060208201905081810360008301526140d481614098565b9050919050565b7f506c616e20737461626c6544656274206d69736d617463680000000000000000600082015250565b60006141116018836132b2565b915061411c826140db565b602082019050919050565b6000602082019050818103600083015261414081614104565b9050919050565b7f506c616e207661726961626c6544656274206d69736d61746368000000000000600082015250565b600061417d601a836132b2565b915061418882614147565b602082019050919050565b600060208201905081810360008301526141ac81614170565b9050919050565b7f506c616e207461636b206d69736d617463680000000000000000000000000000600082015250565b60006141e96012836132b2565b91506141f4826141b3565b602082019050919050565b60006020820190508181036000830152614218816141dc565b9050919050565b7f506c616e20616461695265766973696f6e206d69736d61746368000000000000600082015250565b6000614255601a836132b2565b91506142608261421f565b602082019050919050565b6000602082019050818103600083015261428481614248565b9050919050565b7f4144616920616461695265766973696f6e206d69736d61746368000000000000600082015250565b60006142c1601a836132b2565b91506142cc8261428b565b602082019050919050565b600060208201905081810360008301526142f0816142b4565b9050919050565b600060208201905061430c6000830184613a55565b92915050565b7f6b696e6700000000000000000000000000000000000000000000000000000000815250565b600060408201905061434c60008301614312565b6143596020830184613a55565b92915050565b7f6261720000000000000000000000000000000000000000000000000000000000815250565b60006040820190506143996000830161435f565b6143a66020830184613247565b92915050565b7f4f7261636c6520766174206d69736d6174636800000000000000000000000000600082015250565b60006143e26013836132b2565b91506143ed826143ac565b602082019050919050565b60006020820190508181036000830152614411816143d5565b9050919050565b7f4f7261636c6520696c6b206d69736d6174636800000000000000000000000000600082015250565b600061444e6013836132b2565b915061445982614418565b602082019050919050565b6000602082019050818103600083015261447d81614441565b9050919050565b61448d81613d84565b82525050565b7f706f6f6c00000000000000000000000000000000000000000000000000000000815250565b60006060820190506144ce6000830185614484565b6144da60208301614493565b6144e76040830184613a55565b9392505050565b7f706c616e00000000000000000000000000000000000000000000000000000000815250565b60006060820190506145296000830185614484565b614535602083016144ee565b6145426040830184613a55565b9392505050565b7f7461750000000000000000000000000000000000000000000000000000000000815250565b60006060820190506145846000830185614484565b61459060208301614549565b61459d6040830184613247565b9392505050565b7f6875620000000000000000000000000000000000000000000000000000000000815250565b60006040820190506145de600083016145a4565b6145eb6020830184613a55565b92915050565b7f7069700000000000000000000000000000000000000000000000000000000000815250565b600060608201905061462c6000830185614484565b614638602083016145f1565b6146456040830184613a55565b9392505050565b7f6d61740000000000000000000000000000000000000000000000000000000000815250565b6000819050919050565b600061469761469261468d84614672565b613b28565b61323d565b9050919050565b6146a78161467c565b82525050565b60006060820190506146c26000830185614484565b6146ce6020830161464c565b6146db604083018461469e565b9392505050565b60006020820190506146f76000830184614484565b92915050565b600080600080600060a0868803121561471957614718613363565b5b60006147278882890161351a565b95505060206147388882890161351a565b94505060406147498882890161351a565b935050606061475a8882890161351a565b925050608061476b8882890161351a565b9150509295509295909350565b7f6c696e6500000000000000000000000000000000000000000000000000000000815250565b60006060820190506147b36000830185614484565b6147bf60208301614778565b6147cc6040830184613247565b9392505050565b7f4c696e6500000000000000000000000000000000000000000000000000000000815250565b600060408201905061480d600083016147d3565b61481a6020830184613247565b92915050565b7f4d43445f49414d5f4155544f5f4c494e45000000000000000000000000000000815250565b600060208201905061485a60008301614820565b919050565b60006080820190506148746000830187614484565b6148816020830186613247565b61488e6040830185613247565b61489b6060830184613247565b95945050505050565b7f494c4b5f52454749535452590000000000000000000000000000000000000000815250565b60006020820190506148de600083016148a4565b919050565b600060ff82169050919050565b6148f9816148e3565b811461490457600080fd5b50565b600081519050614916816148f0565b92915050565b60006020828403121561493257614931613363565b5b600061494084828501614907565b91505092915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61498b826132ed565b810181811067ffffffffffffffff821117156149aa576149a9614953565b5b80604052505050565b60006149bd613359565b90506149c98282614982565b919050565b600067ffffffffffffffff8211156149e9576149e8614953565b5b6149f2826132ed565b9050602081019050919050565b6000614a12614a0d846149ce565b6149b3565b905082815260208101848484011115614a2e57614a2d61494e565b5b614a398482856132c3565b509392505050565b600082601f830112614a5657614a55614949565b5b8151614a668482602086016149ff565b91505092915050565b600060208284031215614a8557614a84613363565b5b600082015167ffffffffffffffff811115614aa357614aa2613368565b5b614aaf84828501614a41565b91505092915050565b6000614ad3614ace614ac9846148e3565b613b28565b61323d565b9050919050565b614ae381614ab8565b82525050565b6000819050919050565b6000614b0e614b09614b0484614ae9565b613b28565b61323d565b9050919050565b614b1e81614af3565b82525050565b600061012082019050614b3a600083018c614484565b614b47602083018b613a55565b614b54604083018a613a55565b614b616060830189614ada565b614b6e6080830188614b15565b614b7b60a0830187613a55565b614b8860c0830186613a55565b81810360e0830152614b9a81856132fe565b9050818103610100830152614baf81846132fe565b90509a9950505050505050505050565b600081905092915050565b6000614bd5826132a7565b614bdf8185614bbf565b9350614bef8185602086016132c3565b80840191505092915050565b7f5f504f4f4c000000000000000000000000000000000000000000000000000000600082015250565b6000614c31600583614bbf565b9150614c3c82614bfb565b600582019050919050565b6000614c538284614bca565b9150614c5e82614c24565b915081905092915050565b6000604082019050614c7e6000830185614484565b614c8b6020830184613a55565b9392505050565b7f5f504c414e000000000000000000000000000000000000000000000000000000600082015250565b6000614cc8600583614bbf565b9150614cd382614c92565b600582019050919050565b6000614cea8284614bca565b9150614cf582614cbb565b915081905092915050565b7f5f4f5241434c4500000000000000000000000000000000000000000000000000600082015250565b6000614d36600783614bbf565b9150614d4182614d00565b600782019050919050565b6000614d588284614bca565b9150614d6382614d29565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000614da88261323d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614dda57614dd9613665565b5b60018201905091905056fe323032332d30322d3232204d616b657244414f20457865637574697665205370656c6c207c20486173683a20307861336362666163633533626364656639383633333833623061306531366264383035666232636439646635393537613035653062626539313337336662316238a264697066735822122018348a83d387a788076d71cee52d490fbba98422ccba318ea3c32fa0b813dc3464736f6c63430008100033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100ce5760003560e01c80637284e4161161008c578063ae8421e111610066578063ae8421e1146101cd578063b0604a26146101eb578063f7992d85146101f5578063fe7d47bb14610213576100ce565b80637284e416146101875780638456cb59146101a557806396d373e5146101c3576100ce565b8062a7029b146100d35780630a7a1c4d146100f15780634665096d1461010f57806351973ec91461012d57806351f910661461014b5780636e832f0714610169575b600080fd5b6100db610231565b6040516100e89190610959565b60405180910390f35b6100f96102bf565b60405161010691906109bc565b60405180910390f35b6101176102e3565b60405161012491906109f0565b60405180910390f35b610135610307565b6040516101429190610a6a565b60405180910390f35b61015361031f565b6040516101609190610a9e565b60405180910390f35b610171610343565b60405161017e9190610ad4565b60405180910390f35b61018f6103d9565b60405161019c9190610b44565b60405180910390f35b6101ad610474565b6040516101ba9190610b87565b60405180910390f35b6101cb610498565b005b6101d56105f0565b6040516101e29190610ad4565b60405180910390f35b6101f3610603565b005b6101fd610820565b60405161020a91906109f0565b60405180910390f35b61021b610826565b60405161022891906109f0565b60405180910390f35b6001805461023e90610bd1565b80601f016020809104026020016040519081016040528092919081815260200182805461026a90610bd1565b80156102b75780601f1061028c576101008083540402835291602001916102b7565b820191906000526020600020905b81548152906001019060200180831161029a57829003601f168201915b505050505081565b7f000000000000000000000000ef5dd07891eea254c87cf0451839a5950c9a00ea81565b7f00000000000000000000000000000000000000000000000000000000641d707f81565b73da0ab1e0017debcd72be8599041a2aa3ba7e740f81565b7f2fd06d06a631ac7f72043d007a11442e59f657a7d40a0d7c888692b4e695b38e81565b60007f000000000000000000000000ef5dd07891eea254c87cf0451839a5950c9a00ea73ffffffffffffffffffffffffffffffffffffffff16636e832f076040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d49190610c42565b905090565b60607f000000000000000000000000ef5dd07891eea254c87cf0451839a5950c9a00ea73ffffffffffffffffffffffffffffffffffffffff16637284e4166040518163ffffffff1660e01b8152600401600060405180830381865afa158015610446573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061046f9190610d95565b905090565b7f000000000000000000000000be286431454714f511008713973d3b053a2d38f381565b600260009054906101000a900460ff16156104e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104df90610e2a565b60405180910390fd5b6001600260006101000a81548160ff0219169083151502179055507f000000000000000000000000be286431454714f511008713973d3b053a2d38f373ffffffffffffffffffffffffffffffffffffffff1663168ccd677f000000000000000000000000ef5dd07891eea254c87cf0451839a5950c9a00ea7f2fd06d06a631ac7f72043d007a11442e59f657a7d40a0d7c888692b4e695b38e60016000546040518563ffffffff1660e01b81526004016105a59493929190610ee3565b6000604051808303816000875af11580156105c4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906105ed9190610fd0565b50565b600260009054906101000a900460ff1681565b7f00000000000000000000000000000000000000000000000000000000641d707f421115610666576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065d90611065565b60405180910390fd5b60008054146106aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a1906110f7565b60405180910390fd5b7f000000000000000000000000be286431454714f511008713973d3b053a2d38f373ffffffffffffffffffffffffffffffffffffffff16636a42b8f86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610715573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107399190611143565b42610744919061119f565b6000819055507f000000000000000000000000be286431454714f511008713973d3b053a2d38f373ffffffffffffffffffffffffffffffffffffffff166346d2fbbb7f000000000000000000000000ef5dd07891eea254c87cf0451839a5950c9a00ea7f2fd06d06a631ac7f72043d007a11442e59f657a7d40a0d7c888692b4e695b38e60016000546040518563ffffffff1660e01b81526004016107ec9493929190610ee3565b600060405180830381600087803b15801561080657600080fd5b505af115801561081a573d6000803e3d6000fd5b50505050565b60005481565b60007f000000000000000000000000ef5dd07891eea254c87cf0451839a5950c9a00ea73ffffffffffffffffffffffffffffffffffffffff1663bf0fbcec6000546040518263ffffffff1660e01b815260040161088391906109f0565b602060405180830381865afa1580156108a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c49190611143565b905090565b600081519050919050565b600082825260208201905092915050565b60005b838110156109035780820151818401526020810190506108e8565b60008484015250505050565b6000601f19601f8301169050919050565b600061092b826108c9565b61093581856108d4565b93506109458185602086016108e5565b61094e8161090f565b840191505092915050565b600060208201905081810360008301526109738184610920565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006109a68261097b565b9050919050565b6109b68161099b565b82525050565b60006020820190506109d160008301846109ad565b92915050565b6000819050919050565b6109ea816109d7565b82525050565b6000602082019050610a0560008301846109e1565b92915050565b6000819050919050565b6000610a30610a2b610a268461097b565b610a0b565b61097b565b9050919050565b6000610a4282610a15565b9050919050565b6000610a5482610a37565b9050919050565b610a6481610a49565b82525050565b6000602082019050610a7f6000830184610a5b565b92915050565b6000819050919050565b610a9881610a85565b82525050565b6000602082019050610ab36000830184610a8f565b92915050565b60008115159050919050565b610ace81610ab9565b82525050565b6000602082019050610ae96000830184610ac5565b92915050565b600081519050919050565b600082825260208201905092915050565b6000610b1682610aef565b610b208185610afa565b9350610b308185602086016108e5565b610b398161090f565b840191505092915050565b60006020820190508181036000830152610b5e8184610b0b565b905092915050565b6000610b7182610a37565b9050919050565b610b8181610b66565b82525050565b6000602082019050610b9c6000830184610b78565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680610be957607f821691505b602082108103610bfc57610bfb610ba2565b5b50919050565b6000604051905090565b600080fd5b600080fd5b610c1f81610ab9565b8114610c2a57600080fd5b50565b600081519050610c3c81610c16565b92915050565b600060208284031215610c5857610c57610c0c565b5b6000610c6684828501610c2d565b91505092915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610cb18261090f565b810181811067ffffffffffffffff82111715610cd057610ccf610c79565b5b80604052505050565b6000610ce3610c02565b9050610cef8282610ca8565b919050565b600067ffffffffffffffff821115610d0f57610d0e610c79565b5b610d188261090f565b9050602081019050919050565b6000610d38610d3384610cf4565b610cd9565b905082815260208101848484011115610d5457610d53610c74565b5b610d5f8482856108e5565b509392505050565b600082601f830112610d7c57610d7b610c6f565b5b8151610d8c848260208601610d25565b91505092915050565b600060208284031215610dab57610daa610c0c565b5b600082015167ffffffffffffffff811115610dc957610dc8610c11565b5b610dd584828501610d67565b91505092915050565b7f7370656c6c2d616c72656164792d636173740000000000000000000000000000600082015250565b6000610e14601283610afa565b9150610e1f82610dde565b602082019050919050565b60006020820190508181036000830152610e4381610e07565b9050919050565b60008190508160005260206000209050919050565b60008154610e6c81610bd1565b610e7681866108d4565b94506001821660008114610e915760018114610ea757610eda565b60ff198316865281151560200286019350610eda565b610eb085610e4a565b60005b83811015610ed257815481890152600182019150602081019050610eb3565b808801955050505b50505092915050565b6000608082019050610ef860008301876109ad565b610f056020830186610a8f565b8181036040830152610f178185610e5f565b9050610f2660608301846109e1565b95945050505050565b600067ffffffffffffffff821115610f4a57610f49610c79565b5b610f538261090f565b9050602081019050919050565b6000610f73610f6e84610f2f565b610cd9565b905082815260208101848484011115610f8f57610f8e610c74565b5b610f9a8482856108e5565b509392505050565b600082601f830112610fb757610fb6610c6f565b5b8151610fc7848260208601610f60565b91505092915050565b600060208284031215610fe657610fe5610c0c565b5b600082015167ffffffffffffffff81111561100457611003610c11565b5b61101084828501610fa2565b91505092915050565b7f5468697320636f6e747261637420686173206578706972656400000000000000600082015250565b600061104f601983610afa565b915061105a82611019565b602082019050919050565b6000602082019050818103600083015261107e81611042565b9050919050565b7f54686973207370656c6c2068617320616c7265616479206265656e207363686560008201527f64756c6564000000000000000000000000000000000000000000000000000000602082015250565b60006110e1602583610afa565b91506110ec82611085565b604082019050919050565b60006020820190508181036000830152611110816110d4565b9050919050565b611120816109d7565b811461112b57600080fd5b50565b60008151905061113d81611117565b92915050565b60006020828403121561115957611158610c0c565b5b60006111678482850161112e565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006111aa826109d7565b91506111b5836109d7565b92508282019050808211156111cd576111cc611170565b5b9291505056fea2646970667358221220835bf7694324cdc34d1734d769aec464b6ce171c2d4ee21227eb2ad323876a9f64736f6c63430008100033

Libraries Used


Deployed Bytecode Sourcemap

222175:121:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92960:34;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;93084:37;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;93128:41;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;92820:92;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;93043:34;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;93578:111;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;93450:120;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;93176:36;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;94839:144;;;:::i;:::-;;93001:35;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;94542:289;;;:::i;:::-;;92919:34;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;93697:128;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;92960:34;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;93084:37::-;;;:::o;93128:41::-;;;:::o;92820:92::-;92869:42;92820:92;:::o;93043:34::-;;;:::o;93578:111::-;93624:4;93660:6;93648:31;;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93641:40;;93578:111;:::o;93450:120::-;93496:13;93541:6;93529:31;;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93522:40;;93450:120;:::o;93176:36::-;;;:::o;94839:144::-;94882:4;;;;;;;;;;;94881:5;94873:36;;;;;;;;;;;;:::i;:::-;;;;;;;;;94927:4;94920;;:11;;;;;;;;;;;;;;;;;;94942:5;:10;;;94953:6;94961:3;94966;94971;;94942:33;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;94839:144::o;93001:35::-;;;;;;;;;;;;;:::o;94542:289::-;94607:10;94588:15;:29;;94580:67;;;;;;;;;;;;:::i;:::-;;;;;;;;;94673:1;94666:3;;:8;94658:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;94765:5;94751:26;;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;94733:15;:46;;;;:::i;:::-;94727:3;:52;;;;94790:5;:10;;;94801:6;94809:3;94814;94819;;94790:33;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94542:289::o;92919:34::-;;;;:::o;93697:128::-;93744:16;93792:6;93780:32;;;93813:3;;93780:37;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93773:44;;93697:128;:::o;7:98:1:-;58:6;92:5;86:12;76:22;;7:98;;;:::o;111:168::-;194:11;228:6;223:3;216:19;268:4;263:3;259:14;244:29;;111:168;;;;:::o;285:246::-;366:1;376:113;390:6;387:1;384:13;376:113;;;475:1;470:3;466:11;460:18;456:1;451:3;447:11;440:39;412:2;409:1;405:10;400:15;;376:113;;;523:1;514:6;509:3;505:16;498:27;347:184;285:246;;;:::o;537:102::-;578:6;629:2;625:7;620:2;613:5;609:14;605:28;595:38;;537:102;;;:::o;645:373::-;731:3;759:38;791:5;759:38;:::i;:::-;813:70;876:6;871:3;813:70;:::i;:::-;806:77;;892:65;950:6;945:3;938:4;931:5;927:16;892:65;:::i;:::-;982:29;1004:6;982:29;:::i;:::-;977:3;973:39;966:46;;735:283;645:373;;;;:::o;1024:309::-;1135:4;1173:2;1162:9;1158:18;1150:26;;1222:9;1216:4;1212:20;1208:1;1197:9;1193:17;1186:47;1250:76;1321:4;1312:6;1250:76;:::i;:::-;1242:84;;1024:309;;;;:::o;1339:126::-;1376:7;1416:42;1409:5;1405:54;1394:65;;1339:126;;;:::o;1471:96::-;1508:7;1537:24;1555:5;1537:24;:::i;:::-;1526:35;;1471:96;;;:::o;1573:118::-;1660:24;1678:5;1660:24;:::i;:::-;1655:3;1648:37;1573:118;;:::o;1697:222::-;1790:4;1828:2;1817:9;1813:18;1805:26;;1841:71;1909:1;1898:9;1894:17;1885:6;1841:71;:::i;:::-;1697:222;;;;:::o;1925:77::-;1962:7;1991:5;1980:16;;1925:77;;;:::o;2008:118::-;2095:24;2113:5;2095:24;:::i;:::-;2090:3;2083:37;2008:118;;:::o;2132:222::-;2225:4;2263:2;2252:9;2248:18;2240:26;;2276:71;2344:1;2333:9;2329:17;2320:6;2276:71;:::i;:::-;2132:222;;;;:::o;2360:60::-;2388:3;2409:5;2402:12;;2360:60;;;:::o;2426:142::-;2476:9;2509:53;2527:34;2536:24;2554:5;2536:24;:::i;:::-;2527:34;:::i;:::-;2509:53;:::i;:::-;2496:66;;2426:142;;;:::o;2574:126::-;2624:9;2657:37;2688:5;2657:37;:::i;:::-;2644:50;;2574:126;;;:::o;2706:144::-;2774:9;2807:37;2838:5;2807:37;:::i;:::-;2794:50;;2706:144;;;:::o;2856:167::-;2961:55;3010:5;2961:55;:::i;:::-;2956:3;2949:68;2856:167;;:::o;3029:258::-;3140:4;3178:2;3167:9;3163:18;3155:26;;3191:89;3277:1;3266:9;3262:17;3253:6;3191:89;:::i;:::-;3029:258;;;;:::o;3293:77::-;3330:7;3359:5;3348:16;;3293:77;;;:::o;3376:118::-;3463:24;3481:5;3463:24;:::i;:::-;3458:3;3451:37;3376:118;;:::o;3500:222::-;3593:4;3631:2;3620:9;3616:18;3608:26;;3644:71;3712:1;3701:9;3697:17;3688:6;3644:71;:::i;:::-;3500:222;;;;:::o;3728:90::-;3762:7;3805:5;3798:13;3791:21;3780:32;;3728:90;;;:::o;3824:109::-;3905:21;3920:5;3905:21;:::i;:::-;3900:3;3893:34;3824:109;;:::o;3939:210::-;4026:4;4064:2;4053:9;4049:18;4041:26;;4077:65;4139:1;4128:9;4124:17;4115:6;4077:65;:::i;:::-;3939:210;;;;:::o;4155:99::-;4207:6;4241:5;4235:12;4225:22;;4155:99;;;:::o;4260:169::-;4344:11;4378:6;4373:3;4366:19;4418:4;4413:3;4409:14;4394:29;;4260:169;;;;:::o;4435:377::-;4523:3;4551:39;4584:5;4551:39;:::i;:::-;4606:71;4670:6;4665:3;4606:71;:::i;:::-;4599:78;;4686:65;4744:6;4739:3;4732:4;4725:5;4721:16;4686:65;:::i;:::-;4776:29;4798:6;4776:29;:::i;:::-;4771:3;4767:39;4760:46;;4527:285;4435:377;;;;:::o;4818:313::-;4931:4;4969:2;4958:9;4954:18;4946:26;;5018:9;5012:4;5008:20;5004:1;4993:9;4989:17;4982:47;5046:78;5119:4;5110:6;5046:78;:::i;:::-;5038:86;;4818:313;;;;:::o;5137:148::-;5209:9;5242:37;5273:5;5242:37;:::i;:::-;5229:50;;5137:148;;;:::o;5291:175::-;5400:59;5453:5;5400:59;:::i;:::-;5395:3;5388:72;5291:175;;:::o;5472:266::-;5587:4;5625:2;5614:9;5610:18;5602:26;;5638:93;5728:1;5717:9;5713:17;5704:6;5638:93;:::i;:::-;5472:266;;;;:::o;5744:180::-;5792:77;5789:1;5782:88;5889:4;5886:1;5879:15;5913:4;5910:1;5903:15;5930:320;5974:6;6011:1;6005:4;6001:12;5991:22;;6058:1;6052:4;6048:12;6079:18;6069:81;;6135:4;6127:6;6123:17;6113:27;;6069:81;6197:2;6189:6;6186:14;6166:18;6163:38;6160:84;;6216:18;;:::i;:::-;6160:84;5981:269;5930:320;;;:::o;6256:75::-;6289:6;6322:2;6316:9;6306:19;;6256:75;:::o;6337:117::-;6446:1;6443;6436:12;6460:117;6569:1;6566;6559:12;6583:116;6653:21;6668:5;6653:21;:::i;:::-;6646:5;6643:32;6633:60;;6689:1;6686;6679:12;6633:60;6583:116;:::o;6705:137::-;6759:5;6790:6;6784:13;6775:22;;6806:30;6830:5;6806:30;:::i;:::-;6705:137;;;;:::o;6848:345::-;6915:6;6964:2;6952:9;6943:7;6939:23;6935:32;6932:119;;;6970:79;;:::i;:::-;6932:119;7090:1;7115:61;7168:7;7159:6;7148:9;7144:22;7115:61;:::i;:::-;7105:71;;7061:125;6848:345;;;;:::o;7199:117::-;7308:1;7305;7298:12;7322:117;7431:1;7428;7421:12;7445:180;7493:77;7490:1;7483:88;7590:4;7587:1;7580:15;7614:4;7611:1;7604:15;7631:281;7714:27;7736:4;7714:27;:::i;:::-;7706:6;7702:40;7844:6;7832:10;7829:22;7808:18;7796:10;7793:34;7790:62;7787:88;;;7855:18;;:::i;:::-;7787:88;7895:10;7891:2;7884:22;7674:238;7631:281;;:::o;7918:129::-;7952:6;7979:20;;:::i;:::-;7969:30;;8008:33;8036:4;8028:6;8008:33;:::i;:::-;7918:129;;;:::o;8053:308::-;8115:4;8205:18;8197:6;8194:30;8191:56;;;8227:18;;:::i;:::-;8191:56;8265:29;8287:6;8265:29;:::i;:::-;8257:37;;8349:4;8343;8339:15;8331:23;;8053:308;;;:::o;8367:434::-;8456:5;8481:66;8497:49;8539:6;8497:49;:::i;:::-;8481:66;:::i;:::-;8472:75;;8570:6;8563:5;8556:21;8608:4;8601:5;8597:16;8646:3;8637:6;8632:3;8628:16;8625:25;8622:112;;;8653:79;;:::i;:::-;8622:112;8743:52;8788:6;8783:3;8778;8743:52;:::i;:::-;8462:339;8367:434;;;;;:::o;8821:355::-;8888:5;8937:3;8930:4;8922:6;8918:17;8914:27;8904:122;;8945:79;;:::i;:::-;8904:122;9055:6;9049:13;9080:90;9166:3;9158:6;9151:4;9143:6;9139:17;9080:90;:::i;:::-;9071:99;;8894:282;8821:355;;;;:::o;9182:524::-;9262:6;9311:2;9299:9;9290:7;9286:23;9282:32;9279:119;;;9317:79;;:::i;:::-;9279:119;9458:1;9447:9;9443:17;9437:24;9488:18;9480:6;9477:30;9474:117;;;9510:79;;:::i;:::-;9474:117;9615:74;9681:7;9672:6;9661:9;9657:22;9615:74;:::i;:::-;9605:84;;9408:291;9182:524;;;;:::o;9712:168::-;9852:20;9848:1;9840:6;9836:14;9829:44;9712:168;:::o;9886:366::-;10028:3;10049:67;10113:2;10108:3;10049:67;:::i;:::-;10042:74;;10125:93;10214:3;10125:93;:::i;:::-;10243:2;10238:3;10234:12;10227:19;;9886:366;;;:::o;10258:419::-;10424:4;10462:2;10451:9;10447:18;10439:26;;10511:9;10505:4;10501:20;10497:1;10486:9;10482:17;10475:47;10539:131;10665:4;10539:131;:::i;:::-;10531:139;;10258:419;;;:::o;10683:140::-;10731:4;10754:3;10746:11;;10777:3;10774:1;10767:14;10811:4;10808:1;10798:18;10790:26;;10683:140;;;:::o;10851:827::-;10934:3;10971:5;10965:12;11000:36;11026:9;11000:36;:::i;:::-;11052:70;11115:6;11110:3;11052:70;:::i;:::-;11045:77;;11153:1;11142:9;11138:17;11169:1;11164:164;;;;11342:1;11337:335;;;;11131:541;;11164:164;11248:4;11244:9;11233;11229:25;11224:3;11217:38;11308:6;11301:14;11294:22;11288:4;11284:33;11279:3;11275:43;11268:50;;11164:164;;11337:335;11404:37;11435:5;11404:37;:::i;:::-;11463:1;11477:154;11491:6;11488:1;11485:13;11477:154;;;11565:7;11559:14;11555:1;11550:3;11546:11;11539:35;11615:1;11606:7;11602:15;11591:26;;11513:4;11510:1;11506:12;11501:17;;11477:154;;;11660:1;11655:3;11651:11;11644:18;;11344:328;;11131:541;;10938:740;;10851:827;;;;:::o;11684:634::-;11876:4;11914:3;11903:9;11899:19;11891:27;;11928:71;11996:1;11985:9;11981:17;11972:6;11928:71;:::i;:::-;12009:72;12077:2;12066:9;12062:18;12053:6;12009:72;:::i;:::-;12128:9;12122:4;12118:20;12113:2;12102:9;12098:18;12091:48;12156:73;12224:4;12215:6;12156:73;:::i;:::-;12148:81;;12239:72;12307:2;12296:9;12292:18;12283:6;12239:72;:::i;:::-;11684:634;;;;;;;:::o;12324:307::-;12385:4;12475:18;12467:6;12464:30;12461:56;;;12497:18;;:::i;:::-;12461:56;12535:29;12557:6;12535:29;:::i;:::-;12527:37;;12619:4;12613;12609:15;12601:23;;12324:307;;;:::o;12637:432::-;12725:5;12750:65;12766:48;12807:6;12766:48;:::i;:::-;12750:65;:::i;:::-;12741:74;;12838:6;12831:5;12824:21;12876:4;12869:5;12865:16;12914:3;12905:6;12900:3;12896:16;12893:25;12890:112;;;12921:79;;:::i;:::-;12890:112;13011:52;13056:6;13051:3;13046;13011:52;:::i;:::-;12731:338;12637:432;;;;;:::o;13088:353::-;13154:5;13203:3;13196:4;13188:6;13184:17;13180:27;13170:122;;13211:79;;:::i;:::-;13170:122;13321:6;13315:13;13346:89;13431:3;13423:6;13416:4;13408:6;13404:17;13346:89;:::i;:::-;13337:98;;13160:281;13088:353;;;;:::o;13447:522::-;13526:6;13575:2;13563:9;13554:7;13550:23;13546:32;13543:119;;;13581:79;;:::i;:::-;13543:119;13722:1;13711:9;13707:17;13701:24;13752:18;13744:6;13741:30;13738:117;;;13774:79;;:::i;:::-;13738:117;13879:73;13944:7;13935:6;13924:9;13920:22;13879:73;:::i;:::-;13869:83;;13672:290;13447:522;;;;:::o;13975:175::-;14115:27;14111:1;14103:6;14099:14;14092:51;13975:175;:::o;14156:366::-;14298:3;14319:67;14383:2;14378:3;14319:67;:::i;:::-;14312:74;;14395:93;14484:3;14395:93;:::i;:::-;14513:2;14508:3;14504:12;14497:19;;14156:366;;;:::o;14528:419::-;14694:4;14732:2;14721:9;14717:18;14709:26;;14781:9;14775:4;14771:20;14767:1;14756:9;14752:17;14745:47;14809:131;14935:4;14809:131;:::i;:::-;14801:139;;14528:419;;;:::o;14953:224::-;15093:34;15089:1;15081:6;15077:14;15070:58;15162:7;15157:2;15149:6;15145:15;15138:32;14953:224;:::o;15183:366::-;15325:3;15346:67;15410:2;15405:3;15346:67;:::i;:::-;15339:74;;15422:93;15511:3;15422:93;:::i;:::-;15540:2;15535:3;15531:12;15524:19;;15183:366;;;:::o;15555:419::-;15721:4;15759:2;15748:9;15744:18;15736:26;;15808:9;15802:4;15798:20;15794:1;15783:9;15779:17;15772:47;15836:131;15962:4;15836:131;:::i;:::-;15828:139;;15555:419;;;:::o;15980:122::-;16053:24;16071:5;16053:24;:::i;:::-;16046:5;16043:35;16033:63;;16092:1;16089;16082:12;16033:63;15980:122;:::o;16108:143::-;16165:5;16196:6;16190:13;16181:22;;16212:33;16239:5;16212:33;:::i;:::-;16108:143;;;;:::o;16257:351::-;16327:6;16376:2;16364:9;16355:7;16351:23;16347:32;16344:119;;;16382:79;;:::i;:::-;16344:119;16502:1;16527:64;16583:7;16574:6;16563:9;16559:22;16527:64;:::i;:::-;16517:74;;16473:128;16257:351;;;;:::o;16614:180::-;16662:77;16659:1;16652:88;16759:4;16756:1;16749:15;16783:4;16780:1;16773:15;16800:191;16840:3;16859:20;16877:1;16859:20;:::i;:::-;16854:25;;16893:20;16911:1;16893:20;:::i;:::-;16888:25;;16936:1;16933;16929:9;16922:16;;16957:3;16954:1;16951:10;16948:36;;;16964:18;;:::i;:::-;16948:36;16800:191;;;;:::o

Swarm Source

ipfs://18348a83d387a788076d71cee52d490fbba98422ccba318ea3c32fa0b813dc34

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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