spell-2021-12-03

Created Diff never expires
401 removals
586 lines
370 additions
557 lines
/**
*Submitted for verification at Etherscan.io on 2021-12-06
*/

// hevm: flattened sources of src/DssSpell.sol
// hevm: flattened sources of src/DssSpell.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity =0.6.12 >=0.6.12 <0.7.0;
pragma solidity =0.6.12 >=0.6.12 <0.7.0;
pragma experimental ABIEncoderV2;
pragma experimental ABIEncoderV2;


////// lib/dss-exec-lib/src/CollateralOpts.sol
////// lib/dss-exec-lib/src/CollateralOpts.sol
/* pragma solidity ^0.6.12; */
/* pragma solidity ^0.6.12; */


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


////// lib/dss-exec-lib/src/DssExecLib.sol
////// lib/dss-exec-lib/src/DssExecLib.sol
//
//
// DssExecLib.sol -- MakerDAO Executive Spellcrafting Library
// DssExecLib.sol -- MakerDAO Executive Spellcrafting Library
//
//
// Copyright (C) 2020 Maker Ecosystem Growth Holdings, Inc.
// Copyright (C) 2020 Maker Ecosystem Growth Holdings, Inc.
//
//
// This program is free software: you can redistribute it and/or modify
// 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
// 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
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
// GNU Affero General Public License for more details.
//
//
// You should have received a copy of the GNU Affero General Public License
// 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/>.
// along with this program. If not, see <https://www.gnu.org/licenses/>.
/* pragma solidity ^0.6.12; */
/* pragma solidity ^0.6.12; */
/* pragma experimental ABIEncoderV2; */
/* pragma experimental ABIEncoderV2; */


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


interface Initializable {
interface Initializable {
function init(bytes32) external;
function init(bytes32) external;
}
}


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


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


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


interface Pricing {
interface Pricing {
function poke(bytes32) external;
function poke(bytes32) external;
}
}


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


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


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


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


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


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


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


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


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


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


interface LerpFactoryLike {
interface LerpFactoryLike {
function newLerp(bytes32 name_, address target_, bytes32 what_, uint256 startTime_, uint256 start_, uint256 end_, uint256 duration_) external returns (address);
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);
function newIlkLerp(bytes32 name_, address target_, bytes32 ilk_, bytes32 what_, uint256 startTime_, uint256 start_, uint256 end_, uint256 duration_) external returns (address);
}
}


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




library DssExecLib {
library DssExecLib {


/*****************/
/* WARNING
/*** Constants ***/

/*****************/
The following library code acts as an interface to the actual DssExecLib
library, which can be found in its own deployed contract. Only trust the actual
library's implementation.

*/

address constant public LOG = 0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F;
address constant public LOG = 0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F;

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

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

function add(uint256 x, uint256 y) internal pure returns (uint256 z) {}
/**********************/
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {}
/*** Math Functions ***/
function wdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {}
/**********************/
function rdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {}
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x);
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x - y) <= x);
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
require(y == 0 || (z = x * y) / y == x);
}
function wmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = add(mul(x, y), WAD / 2) / WAD;
}
function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = add(mul(x, y), RAY / 2) / RAY;
}
function wdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = add(mul(x, WAD), y / 2) / y;
}
function rdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = add(mul(x, RAY), y / 2) / y;
}

/****************************/
/*** Core Address Helpers ***/
/****************************/
function dai() public view returns (address) { return getChangelogAddress("MCD_DAI"); }
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 vat() public view returns (address) { return getChangelogAddress("MCD_VAT"); }
function cat() public view returns (address) { return getChangelogAddress("MCD_CAT"); }
function cat() public view returns (address) { return getChangelogAddress("MCD_CAT"); }
function dog() public view returns (address) { return getChangelogAddress("MCD_DOG"); }
function dog() public view returns (address) { return getChangelogAddress("MCD_DOG"); }
function jug() public view returns (address) { return getChangelogAddress("MCD_JUG"); }
function jug() public view returns (address) { return getChangelogAddress("MCD_JUG"); }
function pot() public view returns (address) { return getChangelogAddress("MCD_POT"); }
function pot() public view returns (address) { return getChangelogAddress("MCD_POT"); }
function vow() public view returns (address) { return getChangelogAddress("MCD_VOW"); }
function vow() public view returns (address) { return getChangelogAddress("MCD_VOW"); }
function end() public view returns (address) { return getChangelogAddress("MCD_END"); }
function end() public view returns (address) { return getChangelogAddress("MCD_END"); }
function esm() public view returns (address) { return getChangelogAddress("MCD_ESM"); }
function esm() public view returns (address) { return getChangelogAddress("MCD_ESM"); }
function reg() public view returns (address) { return getChangelogAddress("ILK_REGISTRY"); }
function reg() public view returns (address) { return getChangelogAddress("ILK_REGISTRY"); }
function spotter() public view returns (address) { return getChangelogAddress("MCD_SPOT"); }
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 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 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 autoLine() public view returns (address) { return getChangelogAddress("MCD_IAM_AUTO_LINE"); }
function daiJoin() public view returns (address) { return getChangelogAddress("MCD_JOIN_DAI"); }
function daiJoin() public view returns (address) { return getChangelogAddress("MCD_JOIN_DAI"); }
function lerpFab() public view returns (address) { return getChangelogAddress("LERP_FAB"); }
function lerpFab() public view returns (address) { return getChangelogAddress("LERP_FAB"); }
function clip(bytes32 _ilk) public view returns (address _clip) {}
function flip(bytes32 _ilk) public view returns (address _flip) {}
function calc(bytes32 _ilk) public view returns (address _calc) {}
function getChangelogAddress(bytes32 _key) public view returns (address) {}
function setChangelogAddress(bytes32 _key, address _val) public {}
function setChangelogVersion(string memory _version) public {}
function authorize(address _base, address _ward) public {}
function canCast(uint40 _ts, bool _officeHours) public pure returns (bool) {}
function nextCastTime(uint40 _eta, uint40 _ts, bool _officeHours) public pure returns (uint256 castTime) {}
function updateCollateralPrice(bytes32 _ilk) public {}
function setContract(address _base, bytes32 _what, address _addr) public {}
function setContract(address _base, bytes32 _ilk, bytes32 _what, address _addr) public {}
function setValue(address _base, bytes32 _what, uint256 _amt) public {}
function setValue(address _base, bytes32 _ilk, bytes32 _what, uint256 _amt) public {}
function increaseGlobalDebtCeiling(uint256 _amount) public {}
function setIlkDebtCeiling(bytes32 _ilk, uint256 _amount) public {}
function setIlkAutoLineParameters(bytes32 _ilk, uint256 _amount, uint256 _gap, uint256 _ttl) public {}
function setIlkMinVaultAmount(bytes32 _ilk, uint256 _amount) public {}
function setIlkLiquidationPenalty(bytes32 _ilk, uint256 _pct_bps) public {}
function setIlkMaxLiquidationAmount(bytes32 _ilk, uint256 _amount) public {}
function setIlkLiquidationRatio(bytes32 _ilk, uint256 _pct_bps) public {}
function setStartingPriceMultiplicativeFactor(bytes32 _ilk, uint256 _pct_bps) public {}
function setAuctionTimeBeforeReset(bytes32 _ilk, uint256 _duration) public {}
function setAuctionPermittedDrop(bytes32 _ilk, uint256 _pct_bps) public {}
function setKeeperIncentivePercent(bytes32 _ilk, uint256 _pct_bps) public {}
function setKeeperIncentiveFlatRate(bytes32 _ilk, uint256 _amount) public {}
function setLiquidationBreakerPriceTolerance(address _clip, uint256 _pct_bps) public {}
function setIlkStabilityFee(bytes32 _ilk, uint256 _rate, bool _doDrip) public {}
function setStairstepExponentialDecrease(address _calc, uint256 _duration, uint256 _pct_bps) public {}
function whitelistOracleMedians(address _oracle) public {}
function addReaderToWhitelist(address _oracle, address _reader) public {}
function addReaderToWhitelistCall(address _oracle, address _reader) public {}
function allowOSMFreeze(address _osm, bytes32 _ilk) public {}
function addCollateralBase(
bytes32 _ilk,
address _gem,
address _join,
address _clip,
address _calc,
address _pip
) public {}
function addNewCollateral(CollateralOpts memory co) public {}
function sendPaymentFromSurplusBuffer(address _target, uint256 _amount) public {}
function linearInterpolation(bytes32 _name, address _target, bytes32 _ilk, bytes32 _what, uint256 _startTime, uint256 _start, uint256 _end, uint256 _duration) public returns (address) {}
}


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


function flip(bytes32 _ilk) public view returns (address _flip) {
/* pragma solidity ^0.6.12; */
_flip = RegistryLike(reg()).xlip(_ilk);
}


function calc(bytes32 _ilk) public view returns (address _calc) {
/* import { DssExecLib } from "./DssExecLib.sol"; */
_calc = ClipLike(clip(_ilk)).calc();
/* import { CollateralOpts } from "./CollateralOpts.sol"; */
}


function getChangelogAddress(bytes32 _key) public view returns (address) {
interface OracleLike_1 {
return ChainlogLike(LOG).getAddress(_key);
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.
/*** Changelog Management ***/
// To disable office hours, override this function and
/****************************/
// return false in the inherited action.
/**
function officeHours() public virtual returns (bool) {
@dev Set an address in the MCD on-chain changelog.
return true;
@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);
}
}


/**
// DssExec calls execute. We limit this function subject to officeHours modifier.
@dev Set version in the MCD on-chain changelog.
function execute() external limited {
@param _version Changelog version (e.g. "1.1.2")
actions();
*/
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);
}
}


// 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
/*** Authorizations ***/
// 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 virtual view returns (string memory);
@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
// Returns the next available cast time
@param _ward Address to be authorized
function nextCastTime(uint256 eta) external returns (uint256 castTime) {
*/
require(eta <= uint40(-1));
function authorize(address _base, address _ward) public {
castTime = DssExecLib.nextCastTime(uint40(eta), uint40(block.timestamp), officeHours());
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 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);
}
}
}


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


/**
/* pragma solidity ^0.6.12; */
@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;
}


/**
interface PauseAbstract {
@dev Calculate the next available cast time in epoch seconds
function delay() external view returns (uint256);
@param _eta The scheduled time of the spell plus the pause delay
function plot(address, bytes32, bytes calldata, uint256) external;
@param _ts The current timestamp, usually block.timestamp
function exec(address, bytes32, bytes calldata, uint256) external returns (bytes memory);
@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) {
interface Changelog {
uint256 day = (castTime / 1 days + 3) % 7;
function getAddress(bytes32) external view returns (address);
uint256 hour = castTime / 1 hours % 24;
}
uint256 minute = castTime / 1 minutes % 60;
uint256 second = castTime % 60;


if (day >= 5) {
interface SpellAction {
castTime += (6 - day) * 1 days; // Go to Sunday XX:YY
function officeHours() external view returns (bool);
castTime += (24 - hour + 14) * 1 hours; // Go to 14:YY UTC Monday
function description() external view returns (string memory);
castTime -= minute * 1 minutes + second; // Go to 14:00 UTC
function nextCastTime(uint256) external view returns (uint256);
} else {
}
if (hour >= 21) {

if (day == 4) castTime += 2 days; // If Friday, fast forward to Sunday XX:YY
contract DssExec {
castTime += (24 - hour + 14) * 1 hours; // Go to 14:YY UTC next day

castTime -= minute * 1 minutes + second; // Go to 14:00 UTC
Changelog constant public log = Changelog(0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F);
} else if (hour < 14) {
uint256 public eta;
castTime += (14 - hour) * 1 hours; // Go to 14:YY UTC same day
bytes public sig;
castTime -= minute * 1 minutes + second; // Go to 14:00 UTC
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) {
/*** Accumulating Rates ***/
return SpellAction(action).officeHours();
/**************************/
/**
@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);
}
}


/*********************/
function nextCastTime() external view returns (uint256 castTime) {
/*** Price Updates ***/
return SpellAction(action).nextCastTime(eta);
/*********************/
/**
@dev Update price of a given collateral type.
@param _ilk Collateral type
*/
function updateCollateralPrice(bytes32 _ilk) public {
Pricing(spotter()).poke(_ilk);
}
}


/****************************/
// @param _description A string description of the spell
/*** System Configuration ***/
// @param _expiration The timestamp this spell will expire. (Ex. now + 30 days)
/****************************/
// @param _spellAction The address of the spell action
/**
constructor(uint256 _expiration, address _spellAction) public {
@dev Set a contract in another contract, defining the relationship (ex. set a new Calc contract in Clip)
pause = PauseAbstract(log.getAddress("MCD_PAUSE"));
@param _base The address of the contract where the new contract address will be filed
expiration = _expiration;
@param _what Name of contract to file
action = _spellAction;
@param _addr Address of contract to file

*/
sig = abi.encodeWithSignature("execute()");
function setContract(address _base, bytes32 _what, address _addr) public {
bytes32 _tag; // Required for assembly access
Fileable(_base).file(_what, _addr);
address _action = _spellAction; // Required for assembly access
}
assembly { _tag := extcodehash(_action) }
/**
tag = _tag;
@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);
}
}


/******************************/
function schedule() public {
/*** System Risk Parameters ***/
require(now <= expiration, "This contract has expired");
/******************************/
require(eta == 0, "This spell has already been scheduled");
// function setGlobalDebtCeiling(uint256 _amount) public { setGlobalDebtCeiling(vat(), _amount); }
eta = now + PauseAbstract(pause).delay();
/**
pause.plot(action, tag, sig, eta);
@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", add(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", sub(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", add(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-flap-beg-precision"
setValue(flop(), "beg", add(WAD, wdiv(_pct_bps, BPS_ONE_HUNDRED_PCT)));
}
/**
@dev Set bid duration for debt auctions.
@param _duration Amount of time for bids.
*/
function setDebtAuctionBidDuration(uint256 _duration) public {
setValue(flop(), "ttl", _duration);
}
/**
@dev Set total auction duration for debt auctions.
@param _duration Amount of time for auctions.
*/
function setDebtAuctionDuration(uint256 _duration) public {
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 {
setValue(flop(), "pad", add(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.
function cast() public {
@param _amount The amount to set in DAI (ex. 250,000 DAI amount == 250000)
require(!done, "spell-already-cast");
*/
done = true;
function setMaxTotalDAILiquidationAmount(uint256 _amount) public {
pause.exec(action, tag, sig, eta);
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 sys

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

/* pragma solidity 0.6.12; */
/* pragma experimental ABIEncoderV2; */

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

contract DssSpellAction is DssAction {
// Provides a descriptive tag for bot consumption
// This should be modified weekly to provide a summary of the actions
// Hash: seth keccak -- "$(wget https://raw.githubusercontent.com/makerdao/community/2dfe2a94162345e448c0353ec0e522038572366a/governance/votes/Executive%20vote%20-%20December%203%2C%202021.md -q -O - 2>/dev/null)"
string public constant override description =
"2021-12-03 MakerDAO Executive Spell | Hash: 0x9068bf87d0ec441f57ff92e2544a3df16d42a481b3e94ec2c37a443031833b84";

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

// --- Rates ---
uint256 constant ZERO_ONE_PCT_RATE = 1000000000031693947650284507;
uint256 constant ONE_PCT_RATE = 1000000000315522921573372069;
uint256 constant TWO_PCT_RATE = 1000000000627937192491029810;
uint256 constant TWO_FIVE_PCT_RATE = 1000000000782997609082909351;
uint256 constant TWO_SEVEN_FIVE_PCT_RATE = 1000000000860244400048238898;
uint256 constant THREE_PCT_RATE = 1000000000937303470807876289;
uint256 constant FOUR_PCT_RATE = 1000000001243680656318820312;
uint256 constant SIX_PCT_RATE = 1000000001847694957439350562;
uint256 constant SIX_FIVE_PCT_RATE = 1000000001996917783620820123;

// --- Math ---
uint256 constant MILLION = 10 ** 6;
uint256 constant BILLION = 10 ** 9;

// --- GUNIV3DAIUSDC2-A ---
address constant GUNIV3DAIUSDC2 = 0x50379f632ca68D36E50cfBC8F78fe16bd1499d1e;
address constant MCD_JOIN_GUNIV3DAIUSDC2_A = 0xA7e4dDde3cBcEf122851A7C8F7A55f23c0Daf335;
address constant MCD_CLIP_GUNIV3DAIUSDC2_A = 0xB55da3d3100C4eBF9De755b6DdC24BF209f6cc06;
address constant MCD_CLIP_CALC_GUNIV3DAIUSDC2_A = 0xef051Ca2A2d809ba47ee0FC8caaEd06E3D832225;
address constant PIP_GUNIV3DAIUSDC2 = 0xcCBa43231aC6eceBd1278B90c3a44711a00F4e93;

// --- Wallets ---
address constant COM_WALLET = 0x1eE3ECa7aEF17D1e74eD7C447CcBA61aC76aDbA9;
address constant FLIPFLOPFLAP_WALLET = 0x688d508f3a6B0a377e266405A1583B3316f9A2B3;
address constant FEEDBLACKLOOPS_WALLET = 0x80882f2A36d49fC46C3c654F7f9cB9a2Bf0423e1;
address constant ULTRASCHUPPI_WALLET = 0x89C5d54C979f682F40b73a9FC39F338C88B434c6;
address constant FIELDTECHNOLOGIES_WALLET = 0x0988E41C02915Fe1beFA78c556f946E5F20ffBD3;

function actions() public override {

// ----------------------------- Collateral onboarding -----------------------------
// Add GUNIV3DAIUSDC2-A as a new Vault Type
// https://vote.makerdao.com/polling/QmSkHE8T?network=mainnet#poll-detail
DssExecLib.addNewCollateral(
CollateralOpts({
ilk: "GUNIV3DAIUSDC2-A",
gem: GUNIV3DAIUSDC2,
join: MCD_JOIN_GUNIV3DAIUSDC2_A,
clip: MCD_CLIP_GUNIV3DAIUSDC2_A,
calc: MCD_CLIP_CALC_GUNIV3DAIUSDC2_A,
pip: PIP_GUNIV3DAIUSDC2,
isLiquidatable: false,
isOSM: true,
whitelistOSM: true,
ilkDebtCeiling: 10 * MILLION,
minVaultAmount: 15_000,
maxLiquidationAmount: 5 * MILLION,
liquidationPenalty: 1300,
ilkStabilityFee: ONE_PCT_RATE,
startingPriceFactor: 10500,
breakerTolerance: 9500,
auctionDuration: 220 minutes,
permittedDrop: 9000,
liquidationRatio: 10500,
kprFlatReward: 300,
kprPctReward: 10
})
);

DssExecLib.setStairstepExponentialDecrease(MCD_CLIP_CALC_GUNIV3DAIUSDC2_A, 120 seconds, 9990);
DssExecLib.setIlkAutoLineParameters("GUNIV3DAIUSDC2-A", 10 * MILLION, 10 * MILLION, 8 hours);

// ----------------------------- Rates updates -----------------------------
// https://vote.makerdao.com/polling/QmNqCZGa?network=mainnet
// Increase the ETH-A Stability Fee from 2.5% to 2.75%
DssExecLib.setIlkStabilityFee("ETH-A", TWO_SEVEN_FIVE_PCT_RATE, true);

// Increase the ETH-B Stability Fee from 6.0% to 6.5%
DssExecLib.setIlkStabilityFee("ETH-B", SIX_FIVE_PCT_RATE, true);

// Increase the LINK-A Stability Fee from 1.5% to 2.5%
DssExecLib.setIlkStabilityFee("LINK-A", TWO_FIVE_PCT_RATE, true);

// Increase the MANA-A Stability Fee from 3.0% to 6.0%
DssExecLib.setIlkStabilityFee("MANA-A", SIX_PCT_RATE, true);

// Increase the UNI-A Stability Fee from 1.0% to 3.0%
DssExecLib.setIlkStabilityFee("UNI-A", THREE_PCT_RATE, true);

// Increase the GUSD-A Stability Fee from 0.0% to 1.0%
DssExecLib.setIlkStabilityFee("GUSD-A", ONE_PCT_RATE, true);

// Increase the UNIV2DAIETH-A Stability Fee from 1.5% to 2.0%
DssExecLib.setIlkStabilityFee("UNIV2DAIETH-A", TWO_PCT_RATE, true);

// Increase the UNIV2WBTCETH-A Stability Fee from 2.5% to 3.0%
DssExecLib.setIlkStabilityFee("UNIV2WBTCETH-A", THREE_PCT_RATE, true);

// Increase the UNIV2USDCETH-A Stability Fee from 2.0% to 2.5%
DssExecLib.setIlkStabilityFee("UNIV2USDCETH-A", TWO_FIVE_PCT_RATE, true);

// Increase the UNIV2UNIETH-A Stability Fee from 2.0% to 4.0%
DssExecLib.setIlkStabilityFee("UNIV2UNIETH-A", FOUR_PCT_RATE, true);

// Decrease the GUNIV3DAIUSDC1-A Stability Fee from 0.5% to 0.1%
DssExecLib.setIlkStabilityFee("GUNIV3DAIUSDC1-A", ZERO_ONE_PCT_RATE, true);

// ----------------------------- Debt Ceiling updates -----------------------------
// Increase the WBTC-A Maximum Debt Ceiling (line) from 1.5 billion DAI to 2 billion DAI
// Increase the WBTC-A Target Available Debt (gap) from 60 million DAI to 80 million DAI
// https://vote.makerdao.com/polling/QmNqCZGa?network=mainnet
DssExecLib.setIlkAutoLineParameters("WBTC-A", 2 * BILLION, 80 * MILLION, 6 hours);

// Increase the Dust Para