SAFE Protection
Building and integrating saviour contracts for SAFEs
1. Overview
2. Contract Interface
abstract contract SafeSaviourLike is ReentrancyGuard {
// Checks whether a saviour contract has been approved by governance in the LiquidationEngine
modifier liquidationEngineApproved(address saviour) {
require(liquidationEngine.safeSaviours(saviour) == 1, "SafeSaviour/not-approved-in-liquidation-engine");
_;
}
// Checks whether someone controls a safe handler inside the GebSafeManager
modifier controlsSAFE(address owner, uint256 safeID) {
require(owner != address(0), "SafeSaviour/null-owner");
require(either(owner == safeManager.ownsSAFE(safeID), safeManager.safeCan(safeManager.ownsSAFE(safeID), safeID, owner) == 1), "SafeSaviour/not-owning-safe");
_;
}
// --- Variables ---
LiquidationEngineLike public liquidationEngine;
OracleRelayerLike public oracleRelayer;
GebSafeManagerLike public safeManager;
SAFEEngineLike public safeEngine;
SAFESaviourRegistryLike public saviourRegistry;
// The amount of tokens the keeper gets in exchange for the gas spent to save a SAFE
uint256 public keeperPayout; // [wad]
// The minimum fiat value that the keeper must get in exchange for saving a SAFE
uint256 public minKeeperPayoutValue; // [wad]
/*
The proportion between the keeperPayout (if it's in collateral) and the amount of collateral or debt that's in a SAFE to be saved.
Alternatively, it can be the proportion between the fiat value of keeperPayout and the fiat value of the profit that a keeper
could make if a SAFE is liquidated right now. It ensures there's no incentive to intentionally put a SAFE underwater and then
save it just to make a profit that's greater than the one from participating in collateral auctions
*/
uint256 public payoutToSAFESize;
// --- Constants ---
uint256 public constant ONE = 1;
uint256 public constant HUNDRED = 100;
uint256 public constant THOUSAND = 1000;
uint256 public constant WAD_COMPLEMENT = 10**9;
uint256 public constant WAD = 10**18;
uint256 public constant RAY = 10**27;
uint256 public constant MAX_UINT = uint(-1);
// --- Boolean Logic ---
function both(bool x, bool y) internal pure returns (bool z) {
assembly{ z := and(x, y) }
}
function either(bool x, bool y) internal pure returns (bool z) {
assembly{ z := or(x, y)}
}
// --- Events ---
event SaveSAFE(address indexed keeper, bytes32 indexed collateralType, address indexed safeHandler, uint256 collateralAddedOrDebtRepaid);
// --- Functions to Implement ---
function saveSAFE(address,bytes32,address) virtual external returns (bool,uint256,uint256);
function getKeeperPayoutValue() virtual public returns (uint256);
function keeperPayoutExceedsMinValue() virtual public returns (bool);
function canSave(bytes32,address) virtual external returns (bool);
function tokenAmountUsedToSave(bytes32,address) virtual public returns (uint256);
}3. Implementation Guidelines
Constructor Requirements:
Covering & Uncovering SAFEs:
View Function Requirements:
Saving a SAFE:
4. Monetizing a Saviour
5. Launching on Mainnet
6. Integration Ideas
Last updated
Was this helpful?