/// GlobalSettlement.sol
// Copyright (C) 2018 Rain <rainbreak@riseup.net>
// Copyright (C) 2018 Lev Livnev <lev@liv.nev.org.uk>
//
// 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.7;
abstract contract SAFEEngineLike {
function coinBalance(address) virtual public view returns (uint256);
function collateralTypes(bytes32) virtual public view returns (
uint256 debtAmount, // [wad]
uint256 accumulatedRate, // [ray]
uint256 safetyPrice, // [ray]
uint256 debtCeiling, // [rad]
uint256 debtFloor, // [rad]
uint256 liquidationPrice // [ray]
);
function safes(bytes32,address) virtual public view returns (
uint256 lockedCollateral, // [wad]
uint256 generatedDebt // [wad]
);
function globalDebt() virtual public returns (uint256);
function transferInternalCoins(address src, address dst, uint256 rad) virtual external;
function approveSAFEModification(address) virtual external;
function transferCollateral(bytes32 collateralType, address src, address dst, uint256 wad) virtual external;
function confiscateSAFECollateralAndDebt(bytes32 collateralType, address safe, address collateralSource, address debtDestination, int256 deltaCollateral, int256 deltaDebt) virtual external;
function createUnbackedDebt(address debtDestination, address coinDestination, uint256 rad) virtual external;
function disableContract() virtual external;
}
abstract contract LiquidationEngineLike {
function collateralTypes(bytes32) virtual public view returns (
address collateralAuctionHouse,
uint256 liquidationPenalty, // [wad]
uint256 liquidationQuantity // [rad]
);
function disableContract() virtual external;
}
abstract contract StabilityFeeTreasuryLike {
function disableContract() virtual external;
}
abstract contract AccountingEngineLike {
function disableContract() virtual external;
}
abstract contract CoinSavingsAccountLike {
function disableContract() virtual external;
}
abstract contract CollateralAuctionHouseLike {
function bidAmount(uint id) virtual public view returns (uint256);
function remainingAmountToSell(uint id) virtual public view returns (uint256);
function forgoneCollateralReceiver(uint id) virtual public view returns (address);
function amountToRaise(uint id) virtual public view returns (uint256);
function terminateAuctionPrematurely(uint auctionId) virtual external;
}
abstract contract OracleLike {
function read() virtual public view returns (uint256);
}
abstract contract OracleRelayerLike {
function redemptionPrice() virtual public returns (uint256);
function collateralTypes(bytes32) virtual public view returns (
OracleLike orcl,
uint256 safetyCRatio,
uint256 liquidationCRatio
);
function disableContract() virtual external;
}
/*
This is the Global Settlement module. It is an
involved, stateful process that takes place over nine steps.
First we freeze the system and lock the prices for each collateral type.
1. `shutdownSystem()`:
- freezes user entrypoints
- cancels collateral/surplus auctions
- starts cooldown period
2. `freezeCollateralType(collateralType)`:
- set the final price for each collateralType, reading off the price feed
We must process some system state before it is possible to calculate
the final coin / collateral price. In particular, we need to determine:
a. `collateralShortfall` (considers under-collateralised SAFEs)
b. `outstandingCoinSupply` (after including system surplus / deficit)
We determine (a) by processing all under-collateralised SAFEs with
`processSAFE`
3. `processSAFE(collateralType, safe)`:
- cancels SAFE debt
- any excess collateral remains
- backing collateral taken
We determine (b) by processing ongoing coin generating processes,
i.e. auctions. We need to ensure that auctions will not generate any
further coin income. In the two-way auction model this occurs when
all auctions are in the reverse (`decreaseSoldAmount`) phase. There are two ways
of ensuring this:
4. i) `shutdownCooldown`: set the cooldown period to be at least as long as the
longest auction duration, which needs to be determined by the
shutdown administrator.
This takes a fairly predictable time to occur but with altered
auction dynamics due to the now varying price of the system coin.
ii) `fastTrackAuction`: cancel all ongoing auctions and seize the collateral.
This allows for faster processing at the expense of more
processing calls. This option allows coin holders to retrieve
their collateral faster.
`fastTrackAuction(collateralType, auctionId)`:
- cancel individual collateral auctions in the `increaseBidSize` (forward) phase
- retrieves collateral and returns coins to bidder
- `decreaseSoldAmount` (reverse) phase auctions can continue normally
Option (i), `shutdownCooldown`, is sufficient for processing the system
settlement but option (ii), `fastTrackAuction`, will speed it up. Both options
are available in this implementation, with `fastTrackAuction` being enabled on a
per-auction basis.
When a SAFE has been processed and has no debt remaining, the
remaining collateral can be removed.
5. `freeCollateral(collateralType)`:
- remove collateral from the caller's SAFE
- owner can call as needed
After the processing period has elapsed, we enable calculation of
the final price for each collateral type.
6. `setOutstandingCoinSupply()`:
- only callable after processing time period elapsed
- assumption that all under-collateralised SAFEs are processed
- fixes the total outstanding supply of coin
- may also require extra SAFE processing to cover system surplus
7. `calculateCashPrice(collateralType)`:
- calculate `collateralCashPrice`
- adjusts `collateralCashPrice` in the case of deficit / surplus
At this point we have computed the final price for each collateral
type and coin holders can now turn their coin into collateral. Each
unit coin can claim a fixed basket of collateral.
Coin holders must first `prepareCoinsForRedeeming` into a `coinBag`. Once prepared,
coins cannot be transferred out of the bag. More coin can be added to a bag later.
8. `prepareCoinsForRedeeming(coinAmount)`:
- put some coins into a bag in order to 'redeemCollateral'. The bigger the bag, the more collateral the user can claim.
9. `redeemCollateral(collateralType, collateralAmount)`:
- exchange some coin from your bag for tokens from a specific collateral type
- the amount of collateral available to redeem is limited by how big your bag is
*/
contract GlobalSettlement {
// --- Auth ---
mapping (address => uint) public authorizedAccounts;
function addAuthorization(address account) external isAuthorized {
authorizedAccounts[account] = 1;
emit AddAuthorization(account);
}
function removeAuthorization(address account) external isAuthorized {
authorizedAccounts[account] = 0;
emit RemoveAuthorization(account);
}
modifier isAuthorized {
require(authorizedAccounts[msg.sender] == 1, "GlobalSettlement/account-not-authorized");
_;
}
// --- Data ---
SAFEEngineLike public safeEngine;
LiquidationEngineLike public liquidationEngine;
AccountingEngineLike public accountingEngine;
OracleRelayerLike public oracleRelayer;
CoinSavingsAccountLike public coinSavingsAccount;
StabilityFeeTreasuryLike public stabilityFeeTreasury;
uint256 public contractEnabled;
uint256 public shutdownTime;
uint256 public shutdownCooldown;
uint256 public outstandingCoinSupply; // [rad]
mapping (bytes32 => uint256) public finalCoinPerCollateralPrice; // [ray]
mapping (bytes32 => uint256) public collateralShortfall; // [wad]
mapping (bytes32 => uint256) public collateralTotalDebt; // [wad]
mapping (bytes32 => uint256) public collateralCashPrice; // [ray]
mapping (address => uint256) public coinBag; // [wad]
mapping (bytes32 => mapping (address => uint256)) public coinsUsedToRedeem; // [wad]
// --- Events ---
event AddAuthorization(address account);
event RemoveAuthorization(address account);
event ModifyParameters(bytes32 parameter, uint data);
event ModifyParameters(bytes32 parameter, address data);
event ShutdownSystem();
event FreezeCollateralType(bytes32 collateralType, uint finalCoinPerCollateralPrice);
event FastTrackAuction(bytes32 collateralType, uint256 auctionId, uint256 collateralTotalDebt);
event ProcessSAFE(bytes32 collateralType, address safe, uint256 collateralShortfall);
event FreeCollateral(bytes32 collateralType, address sender, int collateralAmount);
event SetOutstandingCoinSupply(uint256 outstandingCoinSupply);
event CalculateCashPrice(bytes32 collateralType, uint collateralCashPrice);
event PrepareCoinsForRedeeming(address sender, uint coinBag);
event RedeemCollateral(bytes32 collateralType, address sender, uint coinsAmount, uint collateralAmount);
// --- Init ---
constructor() public {
authorizedAccounts[msg.sender] = 1;
contractEnabled = 1;
emit AddAuthorization(msg.sender);
}
// --- Math ---
function addition(uint x, uint y) internal pure returns (uint z) {
z = x + y;
require(z >= x);
}
function subtract(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x);
}
function multiply(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x);
}
function minimum(uint x, uint y) internal pure returns (uint z) {
return x <= y ? x : y;
}
uint constant WAD = 10 ** 18;
uint constant RAY = 10 ** 27;
function rmultiply(uint x, uint y) internal pure returns (uint z) {
z = multiply(x, y) / RAY;
}
function rdivide(uint x, uint y) internal pure returns (uint z) {
z = multiply(x, RAY) / y;
}
function wdivide(uint x, uint y) internal pure returns (uint z) {
z = multiply(x, WAD) / y;
}
// --- Administration ---
function modifyParameters(bytes32 parameter, address data) external isAuthorized {
require(contractEnabled == 1, "GlobalSettlement/contract-not-enabled");
if (parameter == "safeEngine") safeEngine = SAFEEngineLike(data);
else if (parameter == "liquidationEngine") liquidationEngine = LiquidationEngineLike(data);
else if (parameter == "accountingEngine") accountingEngine = AccountingEngineLike(data);
else if (parameter == "oracleRelayer") oracleRelayer = OracleRelayerLike(data);
else if (parameter == "coinSavingsAccount") coinSavingsAccount = CoinSavingsAccountLike(data);
else if (parameter == "stabilityFeeTreasury") stabilityFeeTreasury = StabilityFeeTreasuryLike(data);
else revert("GlobalSettlement/modify-unrecognized-parameter");
emit ModifyParameters(parameter, data);
}
function modifyParameters(bytes32 parameter, uint256 data) external isAuthorized {
require(contractEnabled == 1, "GlobalSettlement/contract-not-enabled");
if (parameter == "shutdownCooldown") shutdownCooldown = data;
else revert("GlobalSettlement/modify-unrecognized-parameter");
emit ModifyParameters(parameter, data);
}
// --- Settlement ---
function shutdownSystem() external isAuthorized {
require(contractEnabled == 1, "GlobalSettlement/contract-not-enabled");
contractEnabled = 0;
shutdownTime = now;
safeEngine.disableContract();
liquidationEngine.disableContract();
// treasury must be disabled before AccountingEngine so that all surplus is gathered in one place
if (address(stabilityFeeTreasury) != address(0)) {
stabilityFeeTreasury.disableContract();
}
accountingEngine.disableContract();
oracleRelayer.disableContract();
if (address(coinSavingsAccount) != address(0)) {
coinSavingsAccount.disableContract();
}
emit ShutdownSystem();
}
function freezeCollateralType(bytes32 collateralType) external {
require(contractEnabled == 0, "GlobalSettlement/contract-still-enabled");
require(finalCoinPerCollateralPrice[collateralType] == 0, "GlobalSettlement/final-collateral-price-already-defined");
(collateralTotalDebt[collateralType],,,,,) = safeEngine.collateralTypes(collateralType);
(OracleLike orcl,,) = oracleRelayer.collateralTypes(collateralType);
// redemptionPrice is a ray, orcl returns a wad
finalCoinPerCollateralPrice[collateralType] = wdivide(oracleRelayer.redemptionPrice(), uint(orcl.read()));
emit FreezeCollateralType(collateralType, finalCoinPerCollateralPrice[collateralType]);
}
function fastTrackAuction(bytes32 collateralType, uint256 auctionId) external {
require(finalCoinPerCollateralPrice[collateralType] != 0, "GlobalSettlement/final-collateral-price-not-defined");
(address auctionHouse_,,) = liquidationEngine.collateralTypes(collateralType);
CollateralAuctionHouseLike collateralAuctionHouse = CollateralAuctionHouseLike(auctionHouse_);
(, uint accumulatedRate,,,,) = safeEngine.collateralTypes(collateralType);
uint bidAmount = collateralAuctionHouse.bidAmount(auctionId);
uint collateralToSell = collateralAuctionHouse.remainingAmountToSell(auctionId);
address forgoneCollateralReceiver = collateralAuctionHouse.forgoneCollateralReceiver(auctionId);
uint amountToRaise = collateralAuctionHouse.amountToRaise(auctionId);
safeEngine.createUnbackedDebt(address(accountingEngine), address(accountingEngine), amountToRaise);
safeEngine.createUnbackedDebt(address(accountingEngine), address(this), bidAmount);
safeEngine.approveSAFEModification(address(collateralAuctionHouse));
collateralAuctionHouse.terminateAuctionPrematurely(auctionId);
uint debt_ = amountToRaise / accumulatedRate;
collateralTotalDebt[collateralType] = addition(collateralTotalDebt[collateralType], debt_);
require(int(collateralToSell) >= 0 && int(debt_) >= 0, "GlobalSettlement/overflow");
safeEngine.confiscateSAFECollateralAndDebt(collateralType, forgoneCollateralReceiver, address(this), address(accountingEngine), int(collateralToSell), int(debt_));
emit FastTrackAuction(collateralType, auctionId, collateralTotalDebt[collateralType]);
}
function processSAFE(bytes32 collateralType, address safe) external {
require(finalCoinPerCollateralPrice[collateralType] != 0, "GlobalSettlement/final-collateral-price-not-defined");
(, uint accumulatedRate,,,,) = safeEngine.collateralTypes(collateralType);
(uint safeCollateral, uint safeDebt) = safeEngine.safes(collateralType, safe);
uint amountOwed = rmultiply(rmultiply(safeDebt, accumulatedRate), finalCoinPerCollateralPrice[collateralType]);
uint minCollateral = minimum(safeCollateral, amountOwed);
collateralShortfall[collateralType] = addition(
collateralShortfall[collateralType],
subtract(amountOwed, minCollateral)
);
require(minCollateral <= 2**255 && safeDebt <= 2**255, "GlobalSettlement/overflow");
safeEngine.confiscateSAFECollateralAndDebt(
collateralType,
safe,
address(this),
address(accountingEngine),
-int(minCollateral),
-int(safeDebt)
);
emit ProcessSAFE(collateralType, safe, collateralShortfall[collateralType]);
}
function freeCollateral(bytes32 collateralType) external {
require(contractEnabled == 0, "GlobalSettlement/contract-still-enabled");
(uint safeCollateral, uint safeDebt) = safeEngine.safes(collateralType, msg.sender);
require(safeDebt == 0, "GlobalSettlement/art-not-zero");
require(safeCollateral <= 2**255, "GlobalSettlement/overflow");
safeEngine.confiscateSAFECollateralAndDebt(
collateralType,
msg.sender,
msg.sender,
address(accountingEngine),
-int(safeCollateral),
0
);
emit FreeCollateral(collateralType, msg.sender, -int(safeCollateral));
}
function setOutstandingCoinSupply() external {
require(contractEnabled == 0, "GlobalSettlement/contract-still-enabled");
require(outstandingCoinSupply == 0, "GlobalSettlement/outstanding-coin-supply-not-zero");
require(safeEngine.coinBalance(address(accountingEngine)) == 0, "GlobalSettlement/surplus-not-zero");
require(now >= addition(shutdownTime, shutdownCooldown), "GlobalSettlement/shutdown-cooldown-not-finished");
outstandingCoinSupply = safeEngine.globalDebt();
emit SetOutstandingCoinSupply(outstandingCoinSupply);
}
function calculateCashPrice(bytes32 collateralType) external {
require(outstandingCoinSupply != 0, "GlobalSettlement/outstanding-coin-supply-zero");
require(collateralCashPrice[collateralType] == 0, "GlobalSettlement/collateral-cash-price-already-defined");
(, uint accumulatedRate,,,,) = safeEngine.collateralTypes(collateralType);
uint256 redemptionAdjustedDebt = rmultiply(
rmultiply(collateralTotalDebt[collateralType], accumulatedRate), finalCoinPerCollateralPrice[collateralType]
);
collateralCashPrice[collateralType] = rdivide(
multiply(subtract(redemptionAdjustedDebt, collateralShortfall[collateralType]), RAY), outstandingCoinSupply
);
emit CalculateCashPrice(collateralType, collateralCashPrice[collateralType]);
}
function prepareCoinsForRedeeming(uint256 coinAmount) external {
require(outstandingCoinSupply != 0, "GlobalSettlement/outstanding-coin-supply-zero");
safeEngine.transferInternalCoins(msg.sender, address(accountingEngine), multiply(coinAmount, RAY));
coinBag[msg.sender] = addition(coinBag[msg.sender], coinAmount);
emit PrepareCoinsForRedeeming(msg.sender, coinBag[msg.sender]);
}
function redeemCollateral(bytes32 collateralType, uint coinsAmount) external {
require(collateralCashPrice[collateralType] != 0, "GlobalSettlement/collateral-cash-price-not-defined");
uint collateralAmount = rmultiply(coinsAmount, collateralCashPrice[collateralType]);
safeEngine.transferCollateral(
collateralType,
address(this),
msg.sender,
collateralAmount
);
coinsUsedToRedeem[collateralType][msg.sender] = addition(coinsUsedToRedeem[collateralType][msg.sender], coinsAmount);
require(coinsUsedToRedeem[collateralType][msg.sender] <= coinBag[msg.sender], "GlobalSettlement/insufficient-bag-balance");
emit RedeemCollateral(collateralType, msg.sender, coinsAmount, collateralAmount);
}
}
{
"compilationTarget": {
"GlobalSettlement.sol": "GlobalSettlement"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"AddAuthorization","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"collateralType","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"collateralCashPrice","type":"uint256"}],"name":"CalculateCashPrice","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"collateralType","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"auctionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralTotalDebt","type":"uint256"}],"name":"FastTrackAuction","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"collateralType","type":"bytes32"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"int256","name":"collateralAmount","type":"int256"}],"name":"FreeCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"collateralType","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"finalCoinPerCollateralPrice","type":"uint256"}],"name":"FreezeCollateralType","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"parameter","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"data","type":"uint256"}],"name":"ModifyParameters","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"parameter","type":"bytes32"},{"indexed":false,"internalType":"address","name":"data","type":"address"}],"name":"ModifyParameters","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"coinBag","type":"uint256"}],"name":"PrepareCoinsForRedeeming","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"collateralType","type":"bytes32"},{"indexed":false,"internalType":"address","name":"safe","type":"address"},{"indexed":false,"internalType":"uint256","name":"collateralShortfall","type":"uint256"}],"name":"ProcessSAFE","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"collateralType","type":"bytes32"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"coinsAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"RedeemCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"RemoveAuthorization","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"outstandingCoinSupply","type":"uint256"}],"name":"SetOutstandingCoinSupply","type":"event"},{"anonymous":false,"inputs":[],"name":"ShutdownSystem","type":"event"},{"inputs":[],"name":"accountingEngine","outputs":[{"internalType":"contract AccountingEngineLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"authorizedAccounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"collateralType","type":"bytes32"}],"name":"calculateCashPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"coinBag","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"coinSavingsAccount","outputs":[{"internalType":"contract CoinSavingsAccountLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"}],"name":"coinsUsedToRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"collateralCashPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"collateralShortfall","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"collateralTotalDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractEnabled","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"collateralType","type":"bytes32"},{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"fastTrackAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"finalCoinPerCollateralPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"collateralType","type":"bytes32"}],"name":"freeCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"collateralType","type":"bytes32"}],"name":"freezeCollateralType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"liquidationEngine","outputs":[{"internalType":"contract LiquidationEngineLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"parameter","type":"bytes32"},{"internalType":"address","name":"data","type":"address"}],"name":"modifyParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"parameter","type":"bytes32"},{"internalType":"uint256","name":"data","type":"uint256"}],"name":"modifyParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracleRelayer","outputs":[{"internalType":"contract OracleRelayerLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"outstandingCoinSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"coinAmount","type":"uint256"}],"name":"prepareCoinsForRedeeming","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"collateralType","type":"bytes32"},{"internalType":"address","name":"safe","type":"address"}],"name":"processSAFE","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"collateralType","type":"bytes32"},{"internalType":"uint256","name":"coinsAmount","type":"uint256"}],"name":"redeemCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeAuthorization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"safeEngine","outputs":[{"internalType":"contract SAFEEngineLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"setOutstandingCoinSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shutdownCooldown","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"shutdownSystem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shutdownTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stabilityFeeTreasury","outputs":[{"internalType":"contract StabilityFeeTreasuryLike","name":"","type":"address"}],"stateMutability":"view","type":"function"}]