// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity =0.8.16 ^0.8.16;
// lib/dss-exec-lib/src/CollateralOpts.sol
//
// CollateralOpts.sol -- Data structure for onboarding collateral
//
// Copyright (C) 2020-2022 Dai Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
struct CollateralOpts {
bytes32 ilk;
address gem;
address join;
address clip;
address calc;
address pip;
bool isLiquidatable;
bool isOSM;
bool whitelistOSM;
uint256 ilkDebtCeiling;
uint256 minVaultAmount;
uint256 maxLiquidationAmount;
uint256 liquidationPenalty;
uint256 ilkStabilityFee;
uint256 startingPriceFactor;
uint256 breakerTolerance;
uint256 auctionDuration;
uint256 permittedDrop;
uint256 liquidationRatio;
uint256 kprFlatReward;
uint256 kprPctReward;
}
// lib/dss-exec-lib/src/DssExec.sol
//
// DssExec.sol -- MakerDAO Executive Spell Template
//
// Copyright (C) 2020-2022 Dai Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
interface PauseAbstract {
function delay() external view returns (uint256);
function plot(address, bytes32, bytes calldata, uint256) external;
function exec(address, bytes32, bytes calldata, uint256) external returns (bytes memory);
}
interface Changelog {
function getAddress(bytes32) external view returns (address);
}
interface SpellAction {
function officeHours() external view returns (bool);
function description() external view returns (string memory);
function nextCastTime(uint256) external view returns (uint256);
}
contract DssExec {
Changelog constant public log = Changelog(0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F);
uint256 public eta;
bytes public sig;
bool public done;
bytes32 immutable public tag;
address immutable public action;
uint256 immutable public expiration;
PauseAbstract immutable public pause;
// Provides a descriptive tag for bot consumption
// This should be modified weekly to provide a summary of the actions
// Hash: seth keccak -- "$(wget https://<executive-vote-canonical-post> -q -O - 2>/dev/null)"
function description() external view returns (string memory) {
return SpellAction(action).description();
}
function officeHours() external view returns (bool) {
return SpellAction(action).officeHours();
}
function nextCastTime() external view returns (uint256 castTime) {
return SpellAction(action).nextCastTime(eta);
}
// @param _description A string description of the spell
// @param _expiration The timestamp this spell will expire. (Ex. block.timestamp + 30 days)
// @param _spellAction The address of the spell action
constructor(uint256 _expiration, address _spellAction) {
pause = PauseAbstract(log.getAddress("MCD_PAUSE"));
expiration = _expiration;
action = _spellAction;
sig = abi.encodeWithSignature("execute()");
bytes32 _tag; // Required for assembly access
address _action = _spellAction; // Required for assembly access
assembly { _tag := extcodehash(_action) }
tag = _tag;
}
function schedule() public {
require(block.timestamp <= expiration, "This contract has expired");
require(eta == 0, "This spell has already been scheduled");
eta = block.timestamp + PauseAbstract(pause).delay();
pause.plot(action, tag, sig, eta);
}
function cast() public {
require(!done, "spell-already-cast");
done = true;
pause.exec(action, tag, sig, eta);
}
}
// lib/dss-exec-lib/src/DssExecLib.sol
//
// DssExecLib.sol -- MakerDAO Executive Spellcrafting Library
//
// Copyright (C) 2020-2022 Dai Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
interface Initializable {
function init(bytes32) external;
}
interface Authorizable {
function rely(address) external;
function deny(address) external;
function setAuthority(address) external;
}
interface Fileable {
function file(bytes32, address) external;
function file(bytes32, uint256) external;
function file(bytes32, bytes32, uint256) external;
function file(bytes32, bytes32, address) external;
}
interface Drippable {
function drip() external returns (uint256);
function drip(bytes32) external returns (uint256);
}
interface Pricing {
function poke(bytes32) external;
}
interface ERC20 {
function decimals() external returns (uint8);
}
interface DssVat {
function hope(address) external;
function nope(address) external;
function ilks(bytes32) external returns (uint256 Art, uint256 rate, uint256 spot, uint256 line, uint256 dust);
function Line() external view returns (uint256);
function suck(address, address, uint256) external;
}
interface ClipLike {
function vat() external returns (address);
function dog() external returns (address);
function spotter() external view returns (address);
function calc() external view returns (address);
function ilk() external returns (bytes32);
}
interface DogLike {
function ilks(bytes32) external returns (address clip, uint256 chop, uint256 hole, uint256 dirt);
}
interface JoinLike {
function vat() external returns (address);
function ilk() external returns (bytes32);
function gem() external returns (address);
function dec() external returns (uint256);
function join(address, uint256) external;
function exit(address, uint256) external;
}
// Includes Median and OSM functions
interface OracleLike_0 {
function src() external view returns (address);
function lift(address[] calldata) external;
function drop(address[] calldata) external;
function setBar(uint256) external;
function kiss(address) external;
function diss(address) external;
function kiss(address[] calldata) external;
function diss(address[] calldata) external;
function orb0() external view returns (address);
function orb1() external view returns (address);
}
interface MomLike {
function setOsm(bytes32, address) external;
function setPriceTolerance(address, uint256) external;
}
interface RegistryLike {
function add(address) external;
function xlip(bytes32) external view returns (address);
}
// https://github.com/makerdao/dss-chain-log
interface ChainlogLike {
function setVersion(string calldata) external;
function setIPFS(string calldata) external;
function setSha256sum(string calldata) external;
function getAddress(bytes32) external view returns (address);
function setAddress(bytes32, address) external;
function removeAddress(bytes32) external;
}
interface IAMLike {
function ilks(bytes32) external view returns (uint256,uint256,uint48,uint48,uint48);
function setIlk(bytes32,uint256,uint256,uint256) external;
function remIlk(bytes32) external;
function exec(bytes32) external returns (uint256);
}
interface LerpFactoryLike {
function newLerp(bytes32 name_, address target_, bytes32 what_, uint256 startTime_, uint256 start_, uint256 end_, uint256 duration_) external returns (address);
function newIlkLerp(bytes32 name_, address target_, bytes32 ilk_, bytes32 what_, uint256 startTime_, uint256 start_, uint256 end_, uint256 duration_) external returns (address);
}
interface LerpLike {
function tick() external returns (uint256);
}
interface RwaOracleLike {
function bump(bytes32 ilk, uint256 val) external;
}
library DssExecLib {
/* WARNING
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;
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;
function jug() public view returns (address) { return getChangelogAddress("MCD_JUG"); }
function pot() public view returns (address) { return getChangelogAddress("MCD_POT"); }
function end() public view returns (address) { return getChangelogAddress("MCD_END"); }
function reg() public view returns (address) { return getChangelogAddress("ILK_REGISTRY"); }
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 setAuthority(address _base, address _authority) 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 setValue(address _base, bytes32 _what, uint256 _amt) public {}
function setValue(address _base, bytes32 _ilk, bytes32 _what, uint256 _amt) public {}
function setDSR(uint256 _rate, bool _doDrip) public {}
function setIlkStabilityFee(bytes32 _ilk, uint256 _rate, bool _doDrip) public {}
function linearInterpolation(bytes32 _name, address _target, bytes32 _ilk, bytes32 _what, uint256 _startTime, uint256 _start, uint256 _end, uint256 _duration) public returns (address) {}
}
// lib/dss-exec-lib/src/DssAction.sol
//
// DssAction.sol -- DSS Executive Spell Actions
//
// Copyright (C) 2020-2022 Dai Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
interface OracleLike_1 {
function src() external view returns (address);
}
abstract contract DssAction {
using DssExecLib for *;
// Modifier used to limit execution time when office hours is enabled
modifier limited {
require(DssExecLib.canCast(uint40(block.timestamp), officeHours()), "Outside office hours");
_;
}
// Office Hours defaults to true by default.
// To disable office hours, override this function and
// return false in the inherited action.
function officeHours() public view virtual returns (bool) {
return true;
}
// DssExec calls execute. We limit this function subject to officeHours modifier.
function execute() external limited {
actions();
}
// DssAction developer must override `actions()` and place all actions to be called inside.
// The DssExec function will call this subject to the officeHours limiter
// By keeping this function public we allow simulations of `execute()` on the actions outside of the cast time.
function actions() public virtual;
// Provides a descriptive tag for bot consumption
// This should be modified weekly to provide a summary of the actions
// Hash: seth keccak -- "$(wget https://<executive-vote-canonical-post> -q -O - 2>/dev/null)"
function description() external view virtual returns (string memory);
// Returns the next available cast time
function nextCastTime(uint256 eta) external view returns (uint256 castTime) {
require(eta <= type(uint40).max);
castTime = DssExecLib.nextCastTime(uint40(eta), uint40(block.timestamp), officeHours());
}
}
// src/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/>.
interface SUsdsLike {
function file(bytes32, uint256) external;
function drip() external returns (uint256);
}
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/b97b2079e2f7ee950676c39f1d67303d19d55fdf/governance/votes/Executive%20vote%20-%20December%206%2C%202024.md' -q -O - 2>/dev/null)"
string public constant override description = "2024-12-06 MakerDAO Executive Spell | Hash: 0xf3154487b58605fd6398364065ba51165e10514f45d063ed3727de31d2b7a3a7";
// Set office hours according to the summary
function officeHours() public pure override returns (bool) {
return false;
}
// ---------- Rates ----------
// Many of the settings that change weekly rely on the rate accumulator
// described at https://docs.makerdao.com/smart-contract-modules/rates-module
// To check this yourself, use the following rate calculation (example 8%):
//
// $ bc -l <<< 'scale=27; e( l(1.08)/(60 * 60 * 24 * 365) )'
//
// A table of rates can be found at
// https://ipfs.io/ipfs/QmVp4mhhbwWGTfbh2BzwQB9eiBrQBKiqcPRZCaAxNUaar6
//
// uint256 internal constant X_PCT_RATE = ;
uint256 internal constant ELEVEN_PT_FIVE_PCT_RATE = 1000000003451750542235895695;
uint256 internal constant TWELVE_PT_TWO_FIVE_PCT_RATE = 1000000003664330950215446102;
uint256 internal constant TWELVE_PT_FIVE_PCT_RATE = 1000000003734875566854894261;
uint256 internal constant TWELVE_PT_SEVEN_FIVE_PCT_RATE = 1000000003805263591546724039;
uint256 internal constant THIRTEEN_PT_TWO_FIVE_PCT_RATE = 1000000003945572635100236468;
uint256 internal constant THIRTEEN_PT_FIVE_PCT_RATE = 1000000004015495027511808328;
uint256 internal constant THIRTEEN_PT_SEVEN_FIVE_PCT_RATE = 1000000004085263575156219812;
uint256 internal constant SIXTEEN_PCT_RATE = 1000000004706367499604668374;
uint256 internal constant SIXTEEN_PT_TWO_FIVE_PCT_RATE = 1000000004774634032180348552;
uint256 internal constant SIXTEEN_PT_SEVEN_FIVE_PCT_RATE = 1000000004910727769570159235;
// ---------- Addresses ----------
address internal immutable SUSDS = DssExecLib.getChangelogAddress("SUSDS");
function actions() public override {
// ---------- Stability Fees Changes ----------
// Forum: https://forum.sky.money/t/out-of-schedule-executive-proposal-stability-scope-parameter-changes-19-sfs-dsr-ssr-spark-effective-dai-borrow-rate-spark-liquidity-layer/25648
// Increase ETH-A Stability Fee by 3.50 percentage points from 9.25% to 12.75%
DssExecLib.setIlkStabilityFee("ETH-A", TWELVE_PT_SEVEN_FIVE_PCT_RATE, /* doDrip = */ true);
// Increase ETH-B Stability Fee by 3.50 percentage points from 9.75% to 13.25%
DssExecLib.setIlkStabilityFee("ETH-B", THIRTEEN_PT_TWO_FIVE_PCT_RATE, /* doDrip = */ true);
// Increase ETH-C Stability Fee by 3.50 percentage points from 9.00% to 12.50%
DssExecLib.setIlkStabilityFee("ETH-C", TWELVE_PT_FIVE_PCT_RATE, /* doDrip = */ true);
// Increase WSTETH-A Stability Fee by 3.50 percentage points from 10.25% to 13.75%
DssExecLib.setIlkStabilityFee("WSTETH-A", THIRTEEN_PT_SEVEN_FIVE_PCT_RATE, /* doDrip = */ true);
// Increase WSTETH-B Stability Fee by 3.50 percentage points from 10.00% to 13.50%
DssExecLib.setIlkStabilityFee("WSTETH-B", THIRTEEN_PT_FIVE_PCT_RATE, /* doDrip = */ true);
// Increase WBTC-A Stability Fee by 4.00 percentage points from 12.25% to 16.25%
DssExecLib.setIlkStabilityFee("WBTC-A", SIXTEEN_PT_TWO_FIVE_PCT_RATE, /* doDrip = */ true);
// Increase WBTC-B Stability Fee by 4.00 percentage points from 12.75% to 16.75%
DssExecLib.setIlkStabilityFee("WBTC-B", SIXTEEN_PT_SEVEN_FIVE_PCT_RATE, /* doDrip = */ true);
// Increase WBTC-C Stability Fee by 4.00 percentage points from 12.00% to 16.00%
DssExecLib.setIlkStabilityFee("WBTC-C", SIXTEEN_PCT_RATE, /* doDrip = */ true);
// Increase ALLOCATOR-SPARK-A Stability Fee by 2.94 percentage points from 9.31% to 12.25%
DssExecLib.setIlkStabilityFee("ALLOCATOR-SPARK-A", TWELVE_PT_TWO_FIVE_PCT_RATE, /* doDrip = */ true);
// ---------- Savings Rate Changes ----------
// Forum: https://forum.sky.money/t/out-of-schedule-executive-proposal-stability-scope-parameter-changes-19-sfs-dsr-ssr-spark-effective-dai-borrow-rate-spark-liquidity-layer/25648
// Increase DSR by 3 percentage points from 8.50% to 11.50%
DssExecLib.setDSR(ELEVEN_PT_FIVE_PCT_RATE, /* doDrip = */ true);
// Increase SSR by 3 percentage points from 9.50% to 12.50%
SUsdsLike(SUSDS).drip();
SUsdsLike(SUSDS).file("ssr", TWELVE_PT_FIVE_PCT_RATE);
}
}
contract DssSpell is DssExec {
constructor() DssExec(block.timestamp + 30 days, address(new DssSpellAction())) {}
}
{
"compilationTarget": {
"DssSpell.sol": "DssSpell"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"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"}]