HAI
This repository contains the core smart contract code for HAI, a GEB fork. GEB is the abbreviation of Gödel, Escher and Bach as well as the name of an Egyptian god.
❱ Getting Started
Welcome to the "Getting Started" guide for the HAI Protocol. If you're new to the system or looking for a concise introduction, you've come to the right place. This section is designed to provide you with a straightforward overview of the essential concepts and steps needed to interact with the HAI ecosystem. Whether you're planning to mint stablecoins, or understand the intricacies of our smart contracts, this guide will equip you with the basic knowledge to take your first steps. Let's dive in!
Introduction to HAI
Introduction to HAI: A Framework for Stablecoin Systems
HAI serves as a framework for creating systems capable of issuing stablecoins. These stablecoins not only act as a reliable source of collateral for other DeFi protocols—when compared to assets like ETH or BTC—but also function as a store of value, complete with an integrated funding rate.
For a comprehensive understanding of the HAI framework, this documentation aims to detail each of its components. We strongly recommend reviewing Reflexer's original whitepaper as a precursor to this documentation.
Core Differentiators of HAI from GEB
HAI is an enhanced fork of GEB, but it comes with several key distinctions:
- Advanced System Parameter Controls: HAI features refined mechanisms for managing system parameters, offering superior flexibility and control.
- Enhanced Deployment and Upgradeability: The framework allows for streamlined deployment and upgrades, simplifying system maintenance.
- Robust Testing and Simulation Suite: HAI includes an upgraded testing and simulation environment, aiding in the identification and mitigation of system risks.
- Emphasis on Multi-Collateral Operations: HAI is designed with a focus on handling multiple types of collateral, broadening its application scope.
- Inclusion of Factories for Common Contract Types: The framework comes with pre-built factories for commonly used contract types, reducing the operations needed for collateral setup.
- Standardized Methods and Contract Utilities: HAI standardizes the way contracts and methods are utilized, making it easier for developers to generate changes across the system.
- Revamped Contract Interactions: The framework restructures the way contracts communicate with each other, leading to more efficient and reliable operations.
By incorporating these features, HAI aims to provide a more advanced, reliable, and user-friendly stablecoin system.
Chainlink Oracles
HAI uses the industry-standard decentralized oracle Chainlink as its primary oracle which provides highly secure and reliable, tamper-resistant data feeds.
Chainlink oracles are used across our Optimism instance:
Asset |
---|
WETH-USD |
wstETH-USD |
tBTC-USD |
rETH-USD |
OP-USD |
SNX-USD |
VELO-USD |
LINK-USD |
RedStone Oracles
HAI uses RedStone Oracles as one of its solutions for crypto assets pricing. RedStone is a Modular Oracle that delivers frequently updated, reliable, and diverse data feeds in a few models. HAI utilizes Push model which ensures that data is pushed into on-chain storage via a relayer with set conditions. (heartbeat and deviation threshold)
HAI Protocol 101
HAI Framework Mechanics
What is HAI?
- Low-Cost: The HAI protocol is deployed on the Optimism network, offering significantly low gas fees for transactions.
- Dollar-Denominated: Both the system coin and the collaterals are denominated in US Dollar.
- Collateral-Backed: A diverse basket of collateral types backs the minting of the system coin.
- Control-Pegged: A PID controller dynamically adjusts the funding rate to balance value transfer between minters (debtors) and holders (creditors).
- Settleable: The system can undergo a Global Settlement, during which all debts are squared and HAI holders can redeem tokens for a share of the collateral pool, regardless of whether they have outstanding debts.
Glossary
Units of Measurement
WEI
: The base unit for raw ERC20 amounts.WAD
: A unit with 18 decimal places, used for representing balances.RAY
: A unit with 27 decimal places, utilized for rate computations.RAD
: A unit with 45 decimal places, employed for calculating owed amounts.Note: The Math Library handles all unit multiplications and divisions.
Tokens
systemCoin
: The ERC20 stablecoin issued by HAI.protocolToken
: The ERC20 governance token, used for system parameter voting and participating in debt/surplus auctions.collateral
: Any ERC20 token that serves as collateral, enhancing the correspondingcType
balance.
Key Concepts
cType
: Represents a unique identifier for a collateral type within the HAI system.COIN
: An internal balance of system coins convertible tosystemCoin
on a1:1
basis.DEBT
: An internal ledger entry representing unbacked debt, erasable withCOIN
on a1:1
basis.SAFE
: A vault-like contract holding collateral and generatingCOINs
, which may also accrueDEBT
.lockedCollateral
: The collateral amount held within aSAFE
.generatedDebt
: The debt incurred by aSAFE
during theCOIN
generation process. Note that it does NOT correlate directly to the amount ofCOINs
generated.- Liquidation: A process triggered for under-collateralized SAFEs, wherein their
generatedDebt
is moved to the system'sDEBT
and collateral is seized for auction to cancel out theDEBT
.
redemptionPrice
: The internal price at which system coins can be exchanged for collateral.targetPrice
: A reference price utilized to adjust theredemptionPrice
, often aligned with market price.redemptionRate
: Governs how theredemptionPrice
changes over time, essentially functioning as the system's funding rate.stabilityFee
: A separate interest rate, unconnected to theredemptionRate
, applied to user debts and collected by the system.accumulatedRate
: Reflects the compoundedstabilityFee
applied to acType
, determining the relationship betweengeneratedDebt
and theCOINs
produced.
This guide aims to provide a comprehensive understanding of HAI's framework and its intricacies. Armed with this knowledge, you'll be better equipped to interact with the protocol effectively.
❱ Core Modules
Welcome to the core contracts that make up the HAI Protocol. This is your go-to resource for understanding the architecture and components that underpin the HAI system. From collateral management and stablecoin issuance to governance and global settlement, these contracts are the building blocks that ensure the protocol's stability, scalability, and security.
Whether you're a developer, a system administrator, or just an enthusiast interested in the mechanics of the HAI Protocol, this index provides detailed information on each core contract and its role within the system. Explore how they interact, understand their functionalities, and learn how they contribute to the robust framework that makes HAI a leader in decentralized finance.
SAFE Engine
See SAFEEngine.sol for more details.
1. Introduction
The SAFE Engine serves as the central component of the HAI framework, managing data on user-owned SAFEs (Simplified Agreement for Future Equity) and the interest rates for different forms of collateral. It performs the following functions:
- Monitoring the debt generated at the system level, by a specific collateral type, or by individual SAFEs.
- Facilitating the internal movement of coins, collateral, or debt between accounts.
- Seizing collateral from SAFEs, usually during liquidation events.
- Managing account permissions.
- Implementing debt caps on a global scale, as well as for each type of collateral and individual SAFE.
Users have the ability to alter the status of their SAFEs via the SAFE Engine, provided that the collateralization ratio remains above the designated minimum threshold.
Notice: The SAFE Engine relies on join adapter contracts to hold the balance of ERC20 tokens of the system. Transfers within the system are handled entirely by the SAFE Engine, which does not handle any ERC20 tokens directly.
2. Contract Details
Key Methods:
Permissioned
transferCollateral
: Transfers collateral from one account to another.transferInternalCoins
: Transfers coins from one account to another.transferSAFECollateralAndDebt
: Transfers collateral and debt from one SAFE to another.modifySAFECollateralization
: Locks/Releases collateral in a SAFE, and/or generates/repays a SAFE's debt.
Authorized
updateCollateralPrice
: Updates the prices of a collateral type.updateAccumulatedRate
: Updates the accumulated rate of a collateral type.modifyCollateralBalance
: Modifies the collateral balance of an account.confiscateSAFECollateralAndDebt
: Confiscates collateral and debt from a SAFE.disableContract
: Locks the SAFEs, accumulated rates, and collateral prices from being modified.
Required Authorities:
- Oracle Relayer: needs authorization to call
updateCollateralPrice
. - Tax Collector: needs authorization to call
updateAccumulatedRate
. - Liquidation Engine: needs authorization to call
confiscateSAFECollateralAndDebt
. - Coin Join: needs authorization to call
transferInternalCoins
. - Collateral Join: needs authorization to call
modifyCollateralBalance
. - Global Settlement: needs authorization to call
disableContract
.
Contract Parameters:
Global
globalDebtCeiling
: The max amount of debt that can be generated by the system.safeDebtCeiling
: The max amount of debt that can be generated by a SAFE.
Per Collateral Type
debtCeiling
: The max amount of debt that can be generated globally by the collateral type.debtFloor
: The min amount of debt that can be generated by a SAFE of that collateral type.
Contract Data:
Global
globalDebt
: The amount of debt that was generated by the system.globalUnbackedDebt
: The amount of debt that was generated by the system and is not backed by collateral.
Per Collateral Type
debtAmount
: The amount of debt that was generated by the collateral type.lockedAmount
: The amount of collateral that is locked in all SAFEs using the collateral type.accumulatedRate
: A value that represents the accumulated interest rate.safetyPrice
: The price of the collateral type (vs HAI) at which the SAFE is considered unsafe.liquidationPrice
: The price of the collateral type (vs HAI) at which the SAFE is considered liquidatable.
A user action should never be able to modify the SAFE collateralization resulting in an unsafe state. When an update the
safetyPrice
leaves the SAFE in an unsafe state, the user may only add collateral and/or repay debt in order to restore the SAFE's collateralization to a safe state.Notice: The
lockedAmount
is a storage variable used to visibilize the total amount of collateral that backs thedebtAmount
. However, this value can be artificially increased, by creating a SAFE without debt and locking collateral in it: on the event of Global Settlement, this user would be allowed to withdraw all of his collateral and it would not be accounted for the redemptions.
3. Key Mechanisms & Concepts
ACCOUNTs vs SAFEs
The SAFE Engine handles 2 different types of entities:
- ACCOUNTs:
- May have coins and collateral (non confiscatable) balance
- May have SAFEs (one for each collateral type)
- May have authorized accounts to modify their balance (or SAFEs)
- May have in some cases (unbacked) debt (confiscatable)
- SAFEs:
- Defined by the account's address (owner) and a collateral type
- May only have locked collateral and generated debt
- May be modified by the owner account, or by authorized accounts
Notice: The protocol may be able to confiscate collateral from SAFEs, but not from ACCOUNTs, all debt generated to ACCOUNTs has is considered unbacked. Core contracts of the protocol may have debt, and they should try to settle it by destroying COINs in their balance.
The Collaterals & SAFEs Accountances
A SAFE consists of the following information:
account
: The address of the owner.collateralType
: The collateral type identifier.generatedDebt
: The amount of debt that was generated.lockedCollateral
: The amount of collateral that is locked in.
The SAFE Engine also tracks per collateral type the following information:
accumulatedRate
: A value that represents the accumulated interest rate.safetyPrice
: The price of the collateral type (vs HAI) at which the SAFE is considered unsafe.liquidationPrice
: The price of the collateral type (vs HAI) at which the SAFE is considered liquidatable
A SAFE is considered healthy when the following condition is met:
lockedCollateral * safetyPrice >= generatedDebt * accumulatedRate
COIN, DEBT, and HAI Dynamics
In this system, COINs and DEBT function similarly to matter and antimatter, created and annulled in pairs. The HAI token acts as the ERC20 counterpart of a COIN when it's outside the system, maintaining a redeemable 1:1 ratio. The system enables users to lock COINs to mint HAI or burn HAI to unlock COINs, making them operable within the framework.
DEBT, when unsecured, can be nullified using COINs on a 1:1 basis. However, within SAFEs, the relationship between generatedDebt
and generated COINs diverges from the 1:1 ratio.
Interest Accumulation
The "accumulated rate" represents the constantly accumulating interest or fees on the outstanding HAI-generated debt. Calculated over time, it's based on the amount of HAI minted and the applicable stability fee rate. This ensures that the debt owed by users evolves due to the ongoing addition of the stability fee. Whenever a user mints or repays HAI, the formula for generatedDebt
is:
coinAmount = generatedDebt * accumulatedRate
Here, coinAmount
is the number of coins the user wishes to mint or burn, and accumulatedRate
is the relevant collateral's accumulated interest rate. The coinAmount
could also be a negative figure, indicating debt dissolution.
Example: Assume a 10% annual interest rate on collateral TKN.
Initially, the
accumulatedRate
is 1. When Alice mints 100 HAI tokens (COINs) from the SAFE Engine, her resulting debt is100 * 1 = 100
.After one year, Alice repays her 100 debt. Now, the
accumulatedRate
stands at 1.1, requiring Alice to repay100 * 1.1 = 110
HAI tokens.Concurrently, Bob mints 100 HAI, resulting in a (
100 / 1.1
)90.9
debt.By year two, the
accumulatedRate
becomes 1.21. To repay his debt, Bob needs90.9 * 1.21 = 110
HAI tokens, identical to Alice's amount.Note: Negative interest rates could technically be implemented using the same mechanics.
Whenever the system refreshes the accumulatedRate
, it leads to a surplus of COINs that get allocated to an unspecified address. This surplus emerges from the updateAccumulatedRate
function, invoked by the Tax Collector. Importantly, these additional COINs are not directly extracted from any SAFE; instead, they manifest as a simultaneous debt increment for all SAFEs holding the taxed collateral type.
Transfer Collateral and Coins events
Since the transfer of collateral and coins is handled by the SAFE Engine, the events TransferCollateral
and TransferInternalCoins
are emitted by the SAFE Engine, and not by the ERC20 contracts. The events emitted by the SAFE Engine try to follow the same structure as the ERC20 events, but with the addition of the collateral type identifier in the TransferCollateral
event.
Generating Debt and minting HAI:
- Lock collateral in a SAFE:
- Deposit TKN:
TransferCollateral(TKN, source, ACCOUNT, amount)
- Lock TKN:
TransferCollateral(TKN, ACCOUNT, 0, amount)
TransferCollateral(TKN, 0, SAFE, amount)
- Generate DEBT:
TransferInternalCoins(0, ACCOUNT, amount)
- Mint HAI:
TransferInternalCoins(ACCOUNT, COIN_JOIN, amount)
ERC20.Transfer(0, destination, amount)
- Deposit TKN:
4. Gotchas
Permissioned vs Authorized
Authorized accounts are addresses allowed to call SAFE Engine isAuthorized
methods. While a SAFE can add approval to an account, which gives permission to the account to modify the SAFE's state (on isSAFEAllowed
methods), this account is not authorized to call SAFE Engine authorized methods (isAuthorized
).
SAFE State vs COIN and DEBT
The generatedDebt
and lockedCollateral
of a SAFE is measured in WAD units, while the COINs and DEBT (that gets limited, for example, by the debt ceilings) are measured in RAD units.
Notice: The reason for this is that the resultant
COIN|DEBT
is calculated by:generatedDebt[WAD] * accumulatedRate[RAY] = COIN|DEBT[RAD]
Collateral Balance vs Locked Collateral
As stated before, an ACCOUNT can have collateral balance, and an account's SAFE can have locked collateral. The difference between these two is that the collateral balance is the amount of collateral that the user has available to use (transfer or withdraw), and the locked collateral is the amount of collateral that the user has locked in a SAFE, that the user would need to modify the SAFE collateralization in order to use.
Unbacked Debt and Debt Settlement
Unbacked debt, or debt that is accounted to an ACCOUNT (not a SAFE with locked collateral) is only generated to contracts of the protocol. This debt can only be settled by having an equal an equal amount of COINs in the ACCOUNT's balance, and calling settleDebt
with the amount of DEBT/COINs to destroy.
This debt is only generated when a SAFE gets liquidated, a portion of the SAFE's collateral is transferred to the Collateral Auction House, the SAFE's debt is transferred to the Accounting Engine (unbacked). The Auction House will the transfer COINs to the Accounting Engine in order for the debt to be settled.
Confiscation of Collateral and Debt
An authorized account may call confiscateSAFECollateralAndDebt
to confiscate the locked collateral and/or debt of a SAFE. This method does not perform any checks on the SAFE's state. The flow of value is inversed when it happens during liquidations, than when the system is under global settlement. This means that this method is always authorized to arbitrarily modify the SAFE's state (and the DEBT balance of an account), even after the system was shutdown.
5. Failure Modes
Parameters misconfiguration
- Low
globalDebtCeiling
may limit user borrowing. - High
globalDebtCeiling
risks debt overload. - Low
safeDebtCeiling
hampers individual borrowing. safeDebtCeiling
aboveglobalDebtCeiling
is likely moot.- Low
cType.debtCeiling
curbs borrowing for specific collateral. cType.debtCeiling
aboveglobalDebtCeiling
is typically irrelevant.- Low
cType.debtFloor
raises liquidation risks. - High
cType.debtFloor
deters small borrowers.
Liquidation mechanics
Despite the fact that the SAFE Engine holds the latest collateral prices and SAFE state, the liquidation of a SAFE is handled by the Liquidation Engine. The Liquidation Engine is authorized to call confiscateSAFECollateralAndDebt
, which doesn't perform healthy checks, and allows it to modify the SAFE's state in an arbitrary way. If the Liquidation Engine (or any authorized address) is misconfigured, it may result in the liquidation of SAFEs that are not unsafe, or malicious modifications to any SAFE's state.
Accumulated Rate and Collateral Prices
Both the updateAccumulatedRate
and updateCollateralPrice
are authorized methods that perform no further checks in the validity of the parameters passed. If the Oracle Relayer or the Tax Collector (or any other authorized address) are misconfigured, it may result in the accumulatedRate
or safetyPrice
being set to an arbitrary value.
If the accumulatedRate
for a given collateral type is set to 0
, the collateral type may be bricked beyond repair, as the accumulatedRate
is iteratively calculated by multiplying the previous value to a multiplier.
Accounting Engine
See AccountingEngine.sol for more details.
1. Introduction
The Accounting Engine serves as the system's financial management hub, overseeing tasks such as:
- Tracking system surplus and deficit.
- Managing system debt through auctions.
- Dealing with system surplus via auctions or transfers.
- Accepting COINs (for instance, from auctions) and using them to offset DEBT.
2. Contract Details
Key Methods:
Public
popDebtFromQueue
: Removes a certain amount of debt from the time-sensitive queue after thepopDebtDelay
duration has elapsed, for either settlement or auction.settleDebt
: Utilizes coin balance to settle debt.cancelAuctionedDebtWithSurplus
: Utilizes coins to settle debt that's in the queue.auctionDebt
: Triggers an auction to liquidate portions of unsettled debt.auctionSurplus
: Triggers an auction to liquidate surplus once all debt has been settled.transferExtraSurplus
: Allocates (instead of auctioning it) excess surplus following debt settlement.transferPostSettlementSurplus
: Allocates all remaining surplus when a Global Settlement event occurs.
Authorized
pushDebtToQueue
: Adds a specified amount of debt to a time-sensitive queue.disableContract
: Deactivates both Debt and Surplus Auction Houses, clears as much debt as possible, and transfers (afterdisableCooldown
delay) any leftover surplus to a designated drain address.
Required Authorities:
- LiquidationEngine: needs authorization to call
pushDebtToQueue
. - Debt Auction House: needs authorization to call
cancelAuctionedDebtWithSurplus
. - Surplus Auction House: needs approval to modify the contract's state in the SAFE Engine.
- Global Settlement: needs authorization to call
disableContract
.
Contract Parameters:
Global
- SAFE Engine: Holds the coin and debt balance, is called to settle debt.
- Surplus Auction House: Is called to start surplus auctions.
- Debt Auction House: Is called to start debt auctions.
postSettlementSurplusDrain
: Address to which surplus is sent following Global Settlement.surplusIsTransferred
: Whether the surplus should be either auctioned off or transferred.surplusDelay
: Time lag before the surplus becomes eligible for either auction or transfer.popDebtDelay
: Time interval after which debt can be popped from the time-sensitive queue.disableCooldown
: The waiting period following Global Settlement, after which any remaining surplus should be transferred.surplusAmount
: Amount of surplus eligible for auction or transfer during each operation.surplusBuffer
: Minimum surplus reserve to be maintained in the contract following an auction or transfer.debtAuctionMintedTokens
: Initial quantity of Protocol Tokens offered for minting in debt auctions.debtAuctionBidSize
: Chunk of debt that can be offered in each individual debt auction.
3. Key Mechanisms & Concepts
Queued Debt, On Auction Debt & Unqueued Unauctioned Debt
Within the SAFE Engine's scope, the Accounting Engine maintains a single debt balance associated with the contract address. This balance is the summation of three components: the queued debt, representing debt in line for auctioning; the unqueued debt, which is currently being auctioned; and the remaining debt not undergoing auction at the moment.
The unqueued-unauctioned debt can be calculated as follows:
unqueuedUnauctionedDebt = debtBalance - queuedDebt - onAuctionDebt
Once the unqueuedUnauctionedDebt
debt reaches the specified debtAuctionBidSize
threshold and the cooldown period elapses, a debt auction is initiated. During this process, the overall debt of the contract remains unchanged, but the onAuctionDebt
metric increases as the debt enters the auction phase. Simultaneously, the calculation for unqueuedUnauctionedDebt
decreases as the debt undergoing auction is accounted for.
4. Gotchas
Unqueued Unauctioned Debt underflow
The queuedDebt
is modified through the pushDebtToQueue
(authorized) and popDebtFromQueue
(public) methods. They don't exclusively mirror the debtBalance
recorded in the SAFE Engine. If an authorized contract uses pushDebtToQueue
without transferring debt to the Accounting Engine, it could lead to an underflow issue (if queuedDebt
exceeds debtBalance
). This situation could potentially disrupt the contract's ability to auction debt as the unqueuedUnauctionedDebt
calculation might underflow and revert.
5. Failure Modes
Parameters misconfiguration
- High
surplusDelay
slows surplus actions. - Low
surplusDelay
rushes surplus auctions. - High
popDebtDelay
delays debt auctions. - Low
popDebtDelay
risks double debt coverage. - High
surplusAmount
risks unfilled surplus auctions. - Low
surplusAmount
hampers surplus actions. - High
surplusBuffer
blocks surplus auctions. - Low
surplusBuffer
risks uncovered new debt. - High
debtAuctionMintedTokens
dilutes protocol tokens. - Low
debtAuctionMintedTokens
risks failed debt auctions. - High
debtAuctionBidSize
risks unfilled debt auctions. - Low
debtAuctionBidSize
slows debt auctions. - Low
shutdownCooldown
risks premature surplus moves. - High
shutdownCooldown
delays post-shutdown surplus actions.
Post Settlement Surplus Drain misconfiguration
The postSettlementSurplusDrain
address should be configured after the system is deployed. It's permissible to leave it unset, but doing so comes with implications: if Global Settlement is activated while this address is not specified, any surplus remaining after the settlement won't be drained. Instead, this surplus can only be used for debt elimination. It's worth noting that once Global Settlement is triggered, the address for postSettlementSurplusDrain
becomes immutable and can't be changed.
Liquidation Engine
See LiquidationEngine.sol for more details.
1. Introduction
The Liquidation Engine is the component responsible for managing the liquidation processes of SAFEs. Its primary duties include:
- Determining the liquidation status of a SAFE.
- Initiating a SAFE Saviour action to enhance the SAFE's financial health, if applicable.
- Assessing the amount of collateral required to be confiscated from a SAFE to offset its debt.
- Activating the process to seize collateral from a SAFE.
- Initiating collateral auctions.
2. Contract Details
Key Functions:
Public
liquidateSAFE
: Evaluates the condition of a SAFE and commences the liquidation process if the SAFE is eligible for liquidation (and if SAFE Saviour intervention fails).
Permissioned
protectSAFE
: Selects a SAFE Saviour to defend a SAFE against liquidation.
Authorized
connectSAFESaviour
: Permits a SAFE Saviour contract to associate with a SAFE for the purpose of preventing its liquidation.disconnectSAFESaviour
: Revokes permission for a SAFE Saviour contract to be linked to SAFEs.removeCoinsFromAuction
: Adjusts the accounted amount of coins that are currently under auction.
Required Authorities:
- Collateral Auction Houses: need authorization to call
removeCoinsFromAuction
. - Global Settlement: needs authorization to call
disableContract
(and block further liquidations).
Contract Parameters:
Global
- SAFE Engine: Holds the SAFE state, is called to confiscate the SAFE collateral and debt.
- Accounting Engine: The confiscated debt is transferred to the Accounting Engine balance, and pushed to its queue to be auctioned.
onAuctionSystemCoinLimit
: Maximum amount of system coins that can be simultaneously auctioned.
Per Collateral Type
- Collateral Auction House: Is called to start collateral auctions.
liquidationPenalty
: Penalty applied to the debt of the SAFE that is being liquidated. This penalty represents an excess in the amount of debt that the collateral auction needs to cover.liquidationQuantity
: Max amount of debt that can be liquidated in each liquidation.
3. Key Mechanisms & Concepts
Liquidation Penalty
If a SAFE is subject to liquidation carrying a specific debt amount, the Liquidation Engine initiates a collateral auction. The target debt to be covered in the auction is determined by the following equation:
debtToAuction = debtToCover * liquidationPenalty
Example: Alice has a SAFE with 1000 TKN locked and a 500 COINs debt. The TKN price drops, and Alice's SAFE gets liquidated. The liquidation penalty is
1.1
, so the collateral auction will auction off Alice's 1000 TKNs, to try to cover 550 COINs of debt.
Liquidation Quantity
The quantity of collateral and debt seized from a SAFE during liquidation is decided based on the following criteria:
- If the SAFE's debt is smaller than
liquidationQuantity
, the SAFE undergoes full liquidation. - If the SAFE's debt surpasses
liquidationQuantity
, the SAFE is only partially liquidated, and residual debt remains. - If the SAFE's outstanding debt crosses the
onAuctionSystemCoinLimit
, partial liquidation occurs, and any remaining debt stays in the SAFE. - In cases of partial liquidation, a corresponding slice of collateral is seized, leaving the remaining collateral intact within the SAFE.
SAFE Saviours
These are smart contracts authorized to intervene on a user's behalf to improve the SAFE's financial condition and prevent liquidation. To become operational, SAFE Saviour contracts must receive authorization and must be chosen by each individual user.
4. Gotchas
System Coin Limit
This parameter establishes a shared upper limit for the total quantity of coins—equivalent to debt—that can be simultaneously auctioned for all kinds of collateral. Once this collective cap is reached, no additional debt auctions can occur, regardless of the type of collateral in question.
Reaching this ceiling can set off a chain reaction of consequences. For example, if a specific collateral type is unusually volatile and maxes out the debt limit through numerous auctions, it could essentially monopolize the available auction capacity, preventing other types of collateral from being auctioned. Furthermore, reaching this ceiling can freeze all new collateral auctions, affecting the liquidity and stability of the system until remedial actions are taken.
Therefore, it's vital for both users and system administrators to closely monitor how near the system is to hitting the onAuctionSystemCoinLimit
. Breaching this limit could disrupt a wide range of operations.
Notice: The
onAuctionSystemCoinLimit
is a number with RAD precision.
5. Failure Modes
Parameters misconfiguration:
- High
onAuctionSystemCoinLimit
risks mass collateral liquidation. - Low
onAuctionSystemCoinLimit
slows SAFE liquidations. - High
liquidationPenalty
amplifies user losses. - Low
liquidationPenalty
encourages overleveraging. - High
liquidationQuantity
favors full SAFE liquidations. - Low
liquidationQuantity
makes small auctions gas-inefficient.
Oracle Relayer
See OracleRelayer.sol for more details.
1. Introduction
The Oracle Relayer is the module that handles the quoting mechanism of the system. It is responsible for the following:
- Storing the oracles addresses for each collateral type.
- Fetching and updating the price of the collateral types.
- Updating the redemption price, given the redemption rate.
2. Contract Details
Key Methods:
Public
marketPrice
: Gets the market price of the system coin.redemptionPrice
: Gets and updates the redemption price.calcRedemptionPrice
: View method that calculates (but does not update) the current redemption price.updateCollateralPrice
: Fetchs the price of a collateral type, updates the redemption price, calculates the safety and liquidation prices, and updates them in the SAFE Engine.
Authorized
updateRedemptionRate
: Updates the redemption rate.
Required Authorities:
- PID Rate Setter: needs authorization to call
updateRedemptionRate
.
Contract Parameters:
Global
- SAFE Engine: Is called to update the collateral prices on it.
- System Coin Oracle: Is queried to fetch the market price of the system coin.
redemptionRateLowerBound
: Lower bound of the redemption rate.redemptionRateUpperBound
: Upper bound of the redemption rate.
Per Collateral Type
- Oracle: Is queried to fetch the price of the collateral type.
safetyCRatio
: Ratio applied to the collateral price to define the safety price.liquidationCRatio
: Ratio applied to the collateral price to define the liquidation price.
3. Key Mechanisms & Concepts
Quoting Mechanism
Each collateral type needs to have an associated oracle that quotes the collateral in terms of the denomination currency (in HAI, US Dollars). The System Coin Oracle needs to be also denominated in the same currency.
The Oracle Relayer handles the quoting mechanism, in which collateral types are quoted in terms of HAI, applying a variable rate to HAI price. The collateral price is calculated as follows:
collateralPrice = oraclePrice / redemptionPrice
C Ratios
Safety and liquidation prices are calculated by applying a ratio to the collateral price. The safety price is calculated as follows:
safetyPrice = collateralPrice * safetyCRatio
liquidationPrice = collateralPrice * liquidationCRatio
The safety price is the price at which the SAFE is considered safe, a user may modify the SAFE collateralization as long as the resulting state is above the safety price.
The liquidation price is the price at which the SAFE is considered liquidatable, and the SAFE may be liquidated.
4. Gotchas
5. Failure Modes
Parameters misconfiguration:
- High
safetyCRatio
limits SAFE modifications. safetyCRatio
nearliquidationCRatio
makes it redundant.- High
liquidationCRatio
may cause needless liquidations. - Low
liquidationCRatio
encourages overleveraging.
Tax Collector
See TaxCollector.sol for more details.
1. Introduction
The Tax Collector is the module that handles the collection of taxes. It is responsible for the following:
- Storing the interest rate for each collateral type.
- Storing the tax revenue receivers.
- Calculating and distributing the tax revenue.
2. Contract Details
Key Methods:
Public
taxSingle
: Calculates and distributes the tax revenue for a single collateral type.taxMany
: Calculates and distributes the tax revenue for a set of collateral types.
Contract Parameters:
Global
- SAFE Engine: Is called to update the accumulated rate for each collateral type.
- Primary Tax Receiver: Receives tax revenue for all collateral types.
globalStabilityFee
: Global stability fee applied to all collateral types.maxStabilityFeeRange
: Maximum range for the stability fee to differ from 1 (no fee).
Per Collateral Type
- Secondary Tax Receivers: Addresses (and tax percentage) that receive revenue for the collateral type total stability fees.
stabilityFee
: Stability fee applied only to the collateral type.
3. Key Mechanisms & Concepts
Primary and Secondary Tax Receivers
The contract holds 2 types of tax receivers:
- Primary Tax Receiver: Is a shared address across all the collateral types. It receives the remaining tax revenue after the secondary tax receivers have been paid.
- Secondary Tax Receivers: Is a set of addresses per collateral type, that can be set to receive a fixed percentage amount of the tax revenue of the collateral type.
Global and Per Collateral Stability Fees
The tax (or Stability Fee) can be configured in 2 ways:
- Global Stability Fee: Shared across all the collateral types.
- Per Collateral Stability Fee: Set for each collateral type.
The final stability fee computed for a collateral type is the multiplication of both fees. To avoid retroactivity, the tax collecting routine first reads the previously stored stability fee, and then calculates and stores the new one.
4. Gotchas
5. Failure Modes
Parameters misconfiguration:
maxStabilityFeeRange
too high may result in a bad calculation of the stability fee, resulting in broken collateral types (as their accumulated rate will be too low/high).maxStabilityFeeRange
too low may result in a bounded value for the stability fee, bounding the final stability fee to a value very similar to 1 (no stability fee).maxSecondaryTaxReceivers
too low may result in not being able to add a secondary tax receiver to a collateral type.- Stability fees (
global * perCollateral
) too high may result in users not interested in generating debt. - Stability fees too low may result in the protocol not being able to generate enough revenue to cover the system expenses.
PID Controller
See PIDController.sol and PIDRateSetter.sol for more details.
1. Introduction
The PID Controller is a smart contract that fine-tunes the system's redemption rate by analyzing the deviation
, which is the discrepancy between the market and redemption prices. It performs the following tasks:
- Computes and stores the system's proportional and integral deviations.
- Applies a decay factor to the integral deviation.
- Adjusts the redemption rate by applying proportional and integral gains to the deviation.
The PID Rate Setter schedules and triggers the PID Controller's redemption rate adjustments.
2. Contract Details
2.1 PID Controller
Key Methods:
Authorized
computeRate
: Computes the new redemption rate, applying the proportional and integral gains to the deviation (can only be called by the PID Rate Setter contract).
Contract Parameters:
- Seed Proposer: Authorized address for initiating redemption rate updates.
integralPeriodSize
: Minimum duration required to calculate integral deviation.perSecondCumulativeLeak
: Decay constant for the integral deviation.noiseBarrier
: Lowest deviation percentage considered for redemption rate adjustment.feedbackOutputUpperBound
: Maximum limit for the redemption rate.feedbackOutputLowerBound
: Minimum limit for the redemption rate.proportionalGain
: Gain factor for proportional deviation.integralGain
: Gain factor for integral deviation.
2.2 PID Rate Setter
Key Methods:
Public
updateRate
: Retrieves market and redemption prices from the Oracle Relayer and prompts the PID Controller to compute the new redemption rate.
Contract Parameters:
updateRateDelay
: Time gap between successive redemption rate adjustments.
3. Key Mechanisms & Concepts
Deviation Metrics
The PID Controller monitors the gap between market and redemption prices and stores both the proportional and integral deviations. Whenever the deviation changes, its integral component is decayed to mitigate the impact of historical deviations on future rates.
Proportional Deviation (pTerm
)
It is computed as:
pTerm = (redemptionPrice - marketPrice) / redemptionPrice
Integral Deviation (iTerm
)
It is calculated iteratively:
iTerm_n = (iTerm_(n-1) * decayFactor) + ((pTerm_n - pTerm_(n-1)) / 2)
Gain Parameters
The system owner can configure the gain parameters for proportional (pGain
) and integral (iGain
) deviations. The redemption rate is then adjusted as follows:
redemptionRate = 1 + (pTerm * pGain + iTerm * iGain)
Notice: All of pTerm, iTerm, pGain, iGain can be negative, so the redemption rate can be lesser than 1 (decrease the rate). Yet the redemption rate can never be 0 or negative.
4. Gotchas
5. Failure Modes
- Invalid
seedProposer
risks stale redemption rate. - High
noiseBarrier
hampers redemption rate adjustment. - High
integralPeriodSize
lowers PID responsiveness. - Over-the-top
feedbackOutputUpperBound
is likely disregarded. - Null
feedbackOutputUpperBound
constrains positive control range. - Excessive
feedbackOutputLowerBound
may be overlooked. - Null
feedbackOutputLowerBound
limits negative control range. - High
perSecondCumulativeLeak
quickens integral decay. - Low
perSecondCumulativeLeak
amplifies integral's historical effect. - High
kp
makes controller jittery to current deviations. - High
ki
overemphasizes historical deviations.
Stability Fee Treasury
See StabilityFeeTreasury.sol for more details.
1. Introduction
The Stability Fee Treasury functions as a specialized contract designed for managing protocol fees that are not factored into the system's surplus or deficit calculations. Unlike locked funds, the funds within this contract remain liquid and can be flexibly utilized by the system owner. Its key responsibilities encompass:
- Facilitating the disbursement of rewards for maintenance tasks.
- Utilizing funds to address unbacked debt.
- Managing diverse payments initiated by the system owner.
- Replenishing the system's surplus/deficit sheets when the treasury surpasses its predefined capacity.
2. Contract Details
Key Methods:
Public
settleDebt
: This function efficiently allocates available funds to cover unbacked debt within the treasury's accounting.transferSurplusFunds
: This operation addresses outstanding debt to the maximum extent achievable and transfers any excess funds beyond the capacity back to the system's surplus/deficit sheets.
Permissioned
takeFunds
: Enables the authorized withdrawal of funds from a consenting address to the treasury.pullFunds
: Allows an address with sufficient allowance to withdraw funds from the treasury.
Authorized
setTotalAllowance
: Grant an address the permission to withdraw funds from the treasury up to a specified limit.setPerHourAllowance
: Assign a per-hour withdrawal limit to an address, allowing them to pull funds from the treasury within this constraint.giveFunds
: Move funds from the treasury to a designated address.disableContract
: Swiftly transfer all available funds from the contract to a predetermined drainage address.
Required Authorities:
- Global Settlement: needs authorization to call
disableContract
.
Contract Parameters:
- SAFEEngine: Query and settle the treasury's coin and debt balance.
- Extra Surplus Receiver: Who receives the funds that are above the treasury's capacity (usually Accounting Engine).
- CoinJoin: Used to join ERC20 HAI into the system.
treasuryCapacity
: Maximum amount of funds that the treasury can hold (before transferring to the extra surplus receiver).pullFundsMinThreshold
: Minimum amount of funds that the treasury must hold to be able to pull funds from it.surplusTransferDelay
: Minimum delay between transfers of funds to the extra surplus receiver.
3. Key Mechanisms & Concepts
4. Gotchas
5. Failure Modes
❱ Auction Houses
Introduction
Auction Houses are core smart contracts in the HAI Protocol that manage debt, surplus, and collateral through automated auctions. Whether you're an active participant or simply interested in HAI's stability mechanisms, understanding these components is crucial.
Types of Auction Houses
- Collateral Auction House: Facilitates the sale of confiscated collateral from liquidated SAFEs, aiming to cover associated debts.
- Debt Auction House: Auctions off the system's debt, offering to mint Protocol Tokens as rewards for debt settlement.
- Surplus Auction House: Manages system surplus, conducting auctions (Protocol Tokens buybacks) to distribute excess funds.
Understanding these mechanisms is essential for navigating the HAI Protocol's automated balance and risk management features.
Collateral Auction House
See CollateralAuctionHouse.sol for more details.
1. Introduction
The Collateral Auction House plays a crucial role in maintaining the stability of the HAI Protocol by handling the auction of collateral seized from undercollateralized SAFEs. The primary objective is to convert this confiscated collateral into system coins, which are then forwarded to the Accounting Engine for debt destruction.
The Collateral Auction House utilizes an increasing discount model. This encourages early bidding by incrementally increasing the discount applied to the collateral over time. The rationale behind this is to expedite the auction process and ensure that debts are covered as swiftly as possible.
2. Contract Details
Key Methods:
Public
buyCollateral
: Enables holders of the system coin to participate in auctions by purchasing available collateral.
Authorized
startAuction
: Initiates a new collateral auction for the contract's specific collateral type.terminateAuctionPrematurely
: Allows for the early termination of an ongoing auction, with any remaining collateral allocated to the caller's address.
Contract Parameters
- Liquidation Engine Address: Specifies the address of the Liquidation Engine, the module responsible for handling the on-auction system coin limit.
- Oracle Relayer Address: Specifies the address of the Oracle Relayer, responsible for providing up-to-date price information.
minimumBid
: Sets the minimum system coin bid required to participate in collateral auctions.minDiscount
: Defines the initial discount rate at which auctions commence.maxDiscount
: Sets the upper limit for the discount rate that auctions can achieve.perSecondDiscountUpdateRate
: Determines the rate at which the discount increases for each second the auction is live.
3. Key Mechanisms & Concepts
Collateral Price Feed and Discount Model
The Collateral Auction House relies on the system's collateral price feed to determine the current market price of the collateral in terms of system coins. Upon establishing this baseline, the contract employs a dynamic discount model to calculate the auction price of the collateral. Here's how the discount model works:
-
Initial Discount: Each auction kicks off with a predefined minimum discount. This discount is set by the
minDiscount
parameter. -
Per-Second Discount Rate: The contract features a rate at which the discount increases on a per-second basis. This rate is determined by the
perSecondDiscountUpdateRate
parameter. -
Maximum Discount Cap: Once the auction reaches the maximum allowable discount, as defined by the
maxDiscount
parameter, the auction remains at this discount level until either all the collateral is bought or the auction is prematurely terminated.
This approach ensures that the auction starts incentivizing early bids but also allows for adjustments over time, ultimately facilitating efficient price discovery and collateral liquidation.
4. Gotchas
5. Failure Modes
Debt Auction House
See DebtAuctionHouse.sol for more details.
1. Introduction
The Debt Auction House contract plays a crucial role in the protocol by managing and auctioning off bad debt. To achieve this, the contract mints protocol tokens, which are auctioned off to users in exchange for system coins. These system coins are then used to annihilate the corresponding bad debt from the system.
The Debt Auction House utilizes a descending bidding model. In this model, a predetermined amount of debt is up for auction. Participants bid by specifying how many protocol tokens they are willing to accept in exchange for taking on this debt. As the auction progresses, the number of protocol tokens a bidder is willing to accept decreases, leading to a more favorable exchange rate for the protocol.
This system ensures that bad debts are efficiently cleared from the protocol, while also incentivizing participants to compete for the most favorable exchange rates.
2. Contract Details
Key Methods:
Public
restartAuction
: Allows for the resumption of an expired auction that has received no bids. This restarts the auction and increases the initial quantity of protocol tokens to be minted as an incentive for participation.decreaseSoldAmount
: Enables users to participate in the auction by bidding. System coins are transferred during this operation.settleAuction
: Finalizes an auction, distributing the protocol tokens to the winning bidder.terminateAuctionPrematurely
: Ends an auction before its scheduled completion. This method creates an unbacked debt entry in the Accounting Engine and returns the system coins to the highest bidder. Note that this action can only be performed when the contract is disabled.
Authorized
startAuction
: Initiates a new debt auction.
Contract Parameters:
- Accounting Engine: The address of the Accounting Engine contract that handles the system's financial records.
These methods and parameters provide a comprehensive control structure for managing bad debt through auctions, balancing both protocol and user interests.
3. Key Mechanisms & Concepts
4. Gotchas
5. Failure Modes
Surplus Auction House
For more details, refer to the SurplusAuctionHouse.sol contract.
1. Introduction
The Surplus Auction House is tasked with auctioning the system's surplus coins in exchange for protocol tokens. A fraction of these protocol tokens is burnt to create a deflationary effect, while the rest is transferred to a specified target address. The auction employs an ascending bidding model: a fixed number of system coins are up for auction, and participants bid by offering increasingly higher amounts of protocol tokens.
2. Contract Details
Key Methods:
Public
increaseBidSize
: Enables users to participate in the auction by offering higher amounts of protocol tokens, which are transferred during this operation.restartAuction
: Resets an expired auction that has not received any bids, making it available for new bids.settleAuction
: Finalizes the auction, transferring the system coins to the winning bidder.terminateAuctionPrematurely
: Aborts an auction before its scheduled completion. This action returns the protocol tokens to the highest bidder but is only possible when the contract is deactivated.
Authorized
startAuction
: Initiates a new surplus auction.
3. Key Mechanisms & Concepts
4. Gotchas
5. Failure Modes
❱ Settlement
The Settlement Module serves as a critical component in the lifecycle of the HAI protocol, governing its shutdown and the subsequent redemption of HAI tokens for underlying collateral. It activates in circumstances that necessitate the halting of the system—such as critical bugs, governance decisions, or market anomalies—to ensure a smooth and orderly unwinding of positions. The module's primary objective is to provide a transparent and fair mechanism for redeeming HAI tokens, thereby ensuring the protocol's integrity even in its termination phase.
Global Settlement
See GlobalSettlement.sol for more details.
1. Introduction
The Global Settlement contract serves as the emergency brake and ultimate wind-down mechanism for the system. Its responsibilities include:
- Triggering the System Shutdown: Initiating the process to safely halt all operations.
- Processing SAFEs: Settling all Secure, Automated, Flexible, and Efficient (SAFE) accounts to determine each collateral's deficits and surplus.
- Terminating Auctions: Bringing all ongoing auctions to a premature end, ensuring that assets are no longer tied up.
- Calculating Redemption Price: Determining the value at which system coin holders can redeem their coins for backing collateral.
- Redemption: Enabling system coin holders to exchange their coins for the appropriate collateral, completing the shutdown process.
This contract is crucial for ensuring that, in the event of a system shutdown, all parties can walk away with assets that are rightfully theirs, thus maintaining a fair and secure environment.
2. Contract Details
Key Methods:
Public
freezeCollateralType
: Captures the current market price of a specified collateral type and freezes it within the contract. This is crucial for ensuring accurate valuations during the shutdown process.fastTrackAuction
: Allows for the immediate termination of ongoing collateral auctions. This function ensures that assets are returned to their rightful owners as quickly as possible during a shutdown.processSAFE
: This method is responsible for settling the debts associated with SAFEs and determining any collateral deficit that exists. This ensures that all assets and liabilities are properly accounted for.freeCollateral
: Post-processing of SAFEs, this function enables SAFE owners to withdraw any remaining collateral. This ensures that users recover their tied-up assets.setOutstandingCoinSupply
: Sets the global coin supply (which also accounts for the system's debt). This is important for calculating how much collateral can be redeemed for each system coin.calculateCashPrice
: Determines the price at which system coin holders can redeem their coins for backing collateral. This provides clarity and fairness in the redemption process.prepareCoinsForRedeeming
: Allows system coin holders to deposit their coins into the contract in preparation for redemption. This sets the stage for users to reclaim their backing collateral.redeemCollateral
: Executes the redemption process, transferring the appropriate amount of collateral to system coin holders who have previously deposited their coins for redemption. This is the final step in the shutdown and asset recovery process.
Authorized
shutdownSystem
: This function triggers the system shutdown, initiating all the processes mentioned above. This function can only be executed by an authorized entity.
These methods collectively enable a structured and secure way to halt system operations, settle accounts, and distribute assets in the event of a system shutdown.
Contract Parameters:
- Oracle Relayer: The address used to fetch the redemption price and the collaterals price.
- Liquidation Engine: The address used to fetch the collateral auction houses from each collateral type.
- Coin Join: The Coin Join contract (to disable).
- Collateral Join Factory: The Collateral Join Factory contract (to disable).
- Collateral Auction House Factory: The Collateral Auction House Factory contract (to disable).
- Stability Fee Treasury: The Stability Fee Treasury contract, that needs to be disabled before the Accounting Engine to transfer its funds to it.
- Accounting Engine: The Accounting Engine contract, that tries after disablement to settle as much debt as possible, and transfer the remaining surplus to the post settlement drain account.
shutdownCooldown
: The amount of time that must pass after the system shutdown is triggered before the outstanding coin supply can be calculated.
3. Key Mechanisms & Concepts
System Shutdown
The system shutdown is triggered by calling the shutdownSystem
method, that triggers the disableContract
method on the disableable contracts (see Disableable.sol). Disableable contracts implement the following tools:
contractEnabled
: A boolean flag that indicates whether the contract is enabled or disabled._onContractDisable
method: A routine that is triggered when the contract is disabled.whenEnabled / whenDisabled
modifiers: Modifiers that can be used to restrict the execution of a method to when the contract is enabled or disabled.
Collateral Redemption Price Calculation
The calculateCashPrice
method plays a critical role in the Global Settlement contract by determining the rate at which each system coin can be redeemed for its underlying collateral. The method employs a complex formula to arrive at this price, ensuring an equitable distribution of collateral assets based on various dynamic factors.
The formula used to calculate the collateral redemption price (collateralCashPrice
) is as follows:
collateralCashPrice =
(
collateralDebt * accumulatedRate / collateralPrice
- collateralShortfall
) / outstandingCoinSupply
Where:
collateralDebt
: Represents the aggregate debt associated with a specific collateral type, generated by SAFEs.accumulatedRate
: The total accrued rate (like interest or tax rate) applied to the specific collateral type over time.collateralPrice
: The most recent market price for the specific collateral type, usually fetched from a trusted oracle.outstandingCoinSupply
: The total circulation of system coins, essentially the aggregate debt of the system.collateralShortfall
: Quantifies the deficit in terms of system coins for the collateral type.If SAFEs for a particular collateral type are under-collateralized, this value will capture the shortfall. Conversely, if SAFEs are over-collateralized, owners are entitled to withdraw the surplus.
Redemption Mechanism:
Once the collateralCashPrice
is calculated, users can redeem their system coins for the backing collateral using the following formula:
redeemableCollateral = coinAmount * collateralCashPrice
This ensures that each coin is redeemable for a fair portion of collateral, aiming to clear out both coins and collateral from the system by the end of the Global Settlement process.
Notice: The design of this formula is such that by the end of the redemption process, the system should ideally have neither excess coins nor remaining collateral. It provides a balanced mechanism for winding down system operations and returning assets to participants.
4. Gotchas
5. Failure Modes
Parameters Misconfiguration
- A too-low
shutdownCooldown
risks premature shutdown, leading to inaccurate collateral redemption prices due to incomplete auctions and unprocessed SAFEs. - A too-high
shutdownCooldown
prolongs the waiting period for users to redeem their coins for backing collateral, causing potential liquidity issues.
Incorrect Authorizations or State
This contract requires to have authorization in the following contracts:
- SAFEEngine
- OracleRelayer
- LiquidationEngine
- CollateralAuctionHouseFactory
- CoinJoin
- CollateralJoinFactory
- StabilityFeeTreasury
- AccountingEngine
Should one of this authorizations be missing, the contract will not work as expected, reverting on the shutdownSystem
routine.
The routine also requires all above contracts to be enabled. Should one of these contracts have been manually disabled, the routine will revert.
Post Settlement Surplus Auction House
See PostSettlmentSurplusAuctionHouse.sol for more details.
1. Introduction
The Post Settlement Surplus Auction House is responsible for auctioning off the surplus coins the system has after the global settlement is triggered. The auctions resemble the Surplus Auction House auctions, with the difference that all of the protocol tokens are burned.
2. Contract Details
Key Methods:
Public
increaseBidSize
: Allows users to bid on the auctions, protocol tokens are transferred in this call.restartAuction
: Restarts an auction that expired with no bids.settleAuction
: Settles an auction, sending the system coins to the winning bidder.
Authorized
startAuction
: Starts a new surplus auction.
3. Key Mechanisms & Concepts
4. Gotchas
5. Failure Modes
Settlement Surplus Actioneer
See SettlementSurplusActioneer.sol for more details.
1. Introduction
The Settlement Surplus Auction Module facilitates the auctioning of surplus coins held by the system following the activation of a global settlement. The module's purpose is grounded in the idea that without conducting an auction, the total circulating coins might fall short of the overall system debt. This imbalance could lead to an increased redemption price for collateral. By orchestrating surplus auctions, the system guarantees an equitable redemption price, while also deterring ill-intentioned actors from exploiting a global settlement to acquire collaterals at a discounted rate.
2. Contract Details
Key Methods:
Public
auctionSurplus
: Triggers a surplus auction and starts the cooldown period.
Contract Parameters:
- Accounting Engine: Used to fetch the surplus auction parameters.
- Surplus Auction House: The Post Settlement Surplus Auction House contract.
Notice: The contract reads the parameters from the Accounting Engine to define the surplus auction cooldown period and the size of the auctions.
3. Key Mechanisms & Concepts
4. Gotchas
5. Failure Modes
❱ Tokens & Utils
This section introduces the ERC20 tokens, and token adaptor contracts, such as CoinJoin and CollateralJoin. These contracts serve as vital bridges between tokens and the smart contract operations, enhancing interoperability and functionality.
System Coin
See SystemCoin.sol for more details.
Protocol Token
See ProtocolToken.sol for more details.
Join Adapters
See CoinJoin.sol, CollateralJoin.sol for more details.
1. Introduction
The Join Adapter contracts assume responsibility for facilitating the seamless movement of collateral and system coin ERC20s into and out of the system. Their functions encompass:
- Safeguarding collateral ERC20 tokens through locking them within the contract, leading to an augmentation of the user's collateral type balance.
- Liberating collateral ERC20 tokens back to the user, thereby diminishing the user's collateral type balance.
- Generating system coin ERC20 tokens through the locking of internal coins within the contract.
- Eradicating system coin ERC20 tokens from the user's holdings, resulting in the release of internal coins to the user.
These contracts engage directly with the SAFE Engine, necessitating occasional user approval to permit the contract to access funds from their account. In the system, a collateral balance is denoted by a specific collateral type string (for example, 'ETH-A', 'OP').
2. Contract Details
2.1 Collateral Join
Key Methods:
join
: This operation secures collateral ERC20 tokens within the contract and augments the collateral type balance of the designated account.exit
: This function liberates collateral ERC20 tokens to the specified account, resulting in a reduction of the user's collateral type balance.
2.2 Coin Join
Key Methods:
exit
: This action involves locking internal coins within the contract and generating system coin ERC20 tokens for the designated account.join
: This function entails releasing internal coins to the specified account while extinguishing system coin ERC20 tokens from the user's holdings.
3. Key Mechanisms & Concepts
System Coin vs Collateral Modes
The system coin ERC20 represents a transferable unit of internal COINs that were initially generated via SAFEs. The ultimate purpose of the system coin ERC20 is to integrate into the system and contribute to the reduction of DEBT. This purpose leads to a reversal in logic between the Coin and Collateral Join contracts concerning the join
and exit
methods.
In the Collateral Join contract, users lock collateral to create an internal balance of a specific collateral type, and they can subsequently burn this internal balance to retrieve their ERC20 tokens. Conversely, in the Coin Join contract, users perform the opposite actions: they burn or mint the system coin ERC20 to respectively release or lock internal coins.
ERC20 Decimal Conversion
To accommodate a diverse array of collaterals and price references, the system employs a standardized unit for establishing balances and quotes, utilizing WAD precision (18 decimals). To ensure this consistency, the Collateral Join contract integrates a conversion factor during the execution of its join and exit methods. This strategy guarantees that users consistently interact with the contract using wei
measurements, which align with the token's inherent precision.
Notice: The CollateralJoin contract supports tokens with less than 18 decimals, but not more.
4. Gotchas
Precision Dust
Due to the potential variance between the precision of the system and that of the ERC20 tokens, users might encounter a situation where their collateral balance is lower than the system's minimum withdrawal threshold. This discrepancy can arise when the amount of collateral falls short of even 1 wei
, which is the smallest unit the system can process for withdrawal purposes.
5. Failure Modes
Global Settlement Mode
When the Coin Join functionality is deactivated, the contract permits the use of the join
method while restricting access to the exit
method. This implies that users retain the ability to convert their system coin ERC20 into internal coins, but they are prevented from generating additional system coin ERC20 tokens.
Conversely, in the event of Collateral Join being disabled, the contract enables the exit
method while prohibiting the use of the join
method. This signifies that users maintain the capability to redeem their collateral ERC20 by burning their corresponding collateral type balance, but they are unable to add more collateral ERC20 tokens to the contract.
On Authorizations
- For Coin Join to mint system coin ERC20, authorization within the System Coin contract is mandatory.
- Prior to interaction, users are required to grant approval within the SAFE Engine for the Coin Join contracts to access and withdraw funds from their account.
- Collateral Join necessitates authorization within the SAFE Engine contract for the purpose of modifying the collateral balance.
- With an active ERC20 balance and SAFE Engine authorization, the Collateral Join contract is capable of withdrawing funds from the user's account.
- The Coin Join contract can effectively burn system coin ERC20 tokens to provide funds to the user's account, provided the user has granted approval within the SAFE Engine and the Coin Join retains an internal coin balance.
Replaceability
Both the Coin and Collateral Join contracts could potentially be superseded by a single new contract through a multi-step process carried out by a single user. This process involves repeating the following sequence:
- Deploy and configure the new Join contract.
- Deactivate the current Join contract.
- For the Collateral Join:
- Execute
exit
on the old (deactivated) contract (reducing the internal balance). - Execute
join
on the new contract (increasing the internal balance). - Execute
exit
on the old contract. - Repeat this sequence until all collateral is successfully transferred.
- Execute
- For the Coin Join:
- Remove authorization for the system coin ERC20 from the old contract.
- Execute
join
on the old (deactivated) contract (increasing the internal balance). - Execute
exit
on the new contract (reducing the internal balance). - Repeat this sequence until all system coin ERC20 tokens are moved.
The primary objective of this procedure is to ensure that both contracts conclude with no funds remaining locked within them. This approach guarantees that the new join contract attains an internal balance equivalent to the amount of ERC20 tokens locked. Subsequently, it's essential to revoke the relevant authorizations from these contracts to complete their deprecation.
❱ Contract Utils
This section provides an in-depth exploration of inheritable utility contracts meticulously crafted to enhance and amplify the capabilities of the protocol. These adaptable utility contracts, when inherited by other protocol contracts, introduce fresh and extended functionalities that enhance the overall development process and consistency of the system. Through a detailed examination of these utilities, readers will gain a deeper understanding of how they contribute to a more robust and harmonized protocol ecosystem.
Authorizable
See Authorizable.sol for more details.
1. Introduction
This abstract contract introduces a fundamental authorization mechanism designed for contracts. It enables a contract to manage authorization for multiple accounts, granting them specific permissions. This is achieved through the use of modifiers, which serve to control and restrict access to designated methods as required.
2. Contract Details
Key Methods:
Authorized
addAuthorization
: Grants authorization to an account.removeAuthorization
: Removes authorization from an account.
Notice: Both methods will revert in the case of a no-operation (i.e. the account is already authorized or unauthorized).
3. Key Mechanisms & Concepts
In the contracts that inherit this functionality, all authorized accounts possess equal access privileges, without any hierarchy of authorization. This implies that any authorized account is capable of both adding and removing authorization for any other account.
4. Gotchas
5. Failure Modes
Modifiable
See Modifiable.sol for more details.
1. Introduction
This abstract contract establishes a standardized mechanism by which contracts can modify their registry and parameters. The available methods are confined to authorized accounts, ensuring that only designated entities have the authority to make these adjustments.
2. Contract Details
Key Methods:
modifyParameters
: Modifies a parameter of the contract._validateParameters
: Hook to validate the parameters after modifying them.
3. Key Mechanisms & Concepts
Standarized Method
The modifyParameters
method is standarized to be shared across contracts that may require different types of parameters. The parameter values are passed as a bytes array, and the inheriting contract is responsible for parsing them (see Encoding).
There are 2 methods that can be used to modify the parameters:
modifyParameters(bytes32 _param, bytes memory _data)
: Modifies a global contract parameter.modifyParameters(bytes32 _cType, bytes32 _param, bytes memory _data)
: Modifies a contract per-collateral parameter.
Parameters Structs
To explicitly define the parameters that can be modified, the contracts should define a parameters struct. Contract parameters that can be modified should be accessed through this struct, and will be read either as params.__param__
or cParams[_cType].__param__
.
Parameters Validation
The _validateParameters
hook is called after modifying the parameters, and can be used to validate the new parameters according to the contract's logic. All contract parameters should be validated, despite they having been modified or not. Common validations may use some of the methods defined in the Assertions library.
As with the modifyParameters
method, there are 2 methods that can be used to validate the parameters:
_validateParameters
: Validates all global contract parameter._validateCParameters
: Validates all contract per-collateral parameter.
Notice: The validation hooks should avoid a parameter that would cause the contract to be set in an undesired way. For example, the OracleRelayer contract implements a check on the liquidation ratio to be always above 100%, else the system would allow for overleveraged positions.
4. Gotchas
Constructors
Contracts that incorporate this functionality must guarantee that their constructors enforce initial parameter validation. This approach serves to prevent the deployment of contracts with invalid parameters. As a result, all validated parameters must be provided as arguments during the contract's construction, ensuring that only valid configurations are utilized upon deployment.
Testing
To thoroughly test the complete implementation of the modifyParameters
method, the testing process should involve fuzzing a parameters struct with all potential values. Subsequently, the method should be called, and the outcome must be validated to confirm that all parameters within the struct have been altered as intended.
To achieve this testing goal, the approach involves comparing the hash of the modified parameters struct with the struct's state obtained from the contract after the modifications have been executed. This rigorous comparison ensures that the method successfully and accurately modifies each parameter as specified.
5. Failure Modes
Disableable
See Disableable.sol for more details.
1. Introduction
This abstract contract introduces a fundamental disable mechanism for contracts. It grants the ability for a contract to be effectively deactivated, and utilizes modifiers to control access to specific methods based on the contract's current state.
2. Contract Details
Key Methods:
Authorized
disableContract
: Disables the contract.
Internal
_onContractDisable
: Hook to be called when the contract is disabled._isEnabled
: Checks if the contract is enabled.
Modifiers
whenEnabled
: Restricts access to the method to when the contract is enabled.whenDisabled
: Restricts access to the method to when the contract is disabled.
3. Key Mechanisms & Concepts
4. Gotchas
5. Failure Modes
❱ Factories
This section introduces a collection of essential contracts designed to streamline the creation and operation of various factory-related components. These contracts, alongside their accompanying utility modules, are specifically engineered to be inherited within the context of factory contracts. By leveraging these building blocks, developers can expedite the process of constructing, managing, and optimizing factory contracts with enhanced efficiency and reliability.
FactoryChild
See FactoryChild.sol for more details.
1. Introduction
This abstract contract is inherited by all contracts that are deployed through a factory. It provides a reference to the parent factory.
2. Contract Details
Key Methods:
factory
: Returns the parent factory.
3. Key Mechanisms & Concepts
The rationale behind this contract is to provide a way of extending contracts that are standalone deployable, to be deployed through a factory. Contracts that are factory deployed can also implement other factory related utils, such as AuthorizableChild or DisableableChild.
4. Gotchas
Constructors
Contracts which only change from the standalone version is the constructor routine should not create a new instance of the contract, but be considered as another child implementation of the same contract. This is the case of the CollateralJoinDelegatableChild, which is a child implementation of the CollateralJoin contract, that calls the ERC20Votes.delegate
method on constructor.
5. Failure Modes
AuthorizableChild
See AuthorizableChild.sol for more details.
1. Introduction
This abstract contract extends the Authorizable contract for factory deployed instances, to allow for a contract to be authorized in the parent factory, and still be able to access restricted methods.
2. Contract Details
Overrides
_isAuthorized
: internal method to check if the sender is authorized in the contract or the parent factory.
3. Key Mechanisms & Concepts
The contract will check if the sender is authorized in the contract or the parent factory.
4. Gotchas
5. Failure Modes
DisableableChild
See DisableableChild.sol for more details.
1. Introduction
This abstract contract extends the Disableable contract for factory deployed instances, to allow for the parent factory to be disabled, and extend the disabled state to all the child contracts.
2. Contract Details
Overrides
_isEnabled
: internal method to check if the contract AND the parent factory are enabled._onContractDisable
: can only be called by the parent factory.
3. Key Mechanisms & Concepts
The contract will check if the contract AND the parent factory are enabled. If either is disabled, the contract is considered disabled.
4. Gotchas
Contracts that inherit this contract can only be disabled by the parent factory. In that way, the factory can keep track of all the enabled contracts that have been deployed through it.
5. Failure Modes
❱ Proxy Utils
One of the core components of the HAI ecosystem is the HAI Safe Manager and Proxy Contracts. These smart contracts are designed to provide a secure and efficient way to interact with the HAI protocol, enabling users to manage their SAFEs and assets, and execute transactions in a streamlined manner.
HAI Proxy
See HaiProxy.sol for more details.
1. Introduction
The HAI Proxy contract is a powerful and flexible smart contract commonly used within the decentralized finance (DeFi) ecosystem. Its primary function is to act as an extensible, personal proxy contract that allows users to bundle multiple actions into single, atomic transactions. With HAI Proxy, users can interact with multiple smart contracts or execute complex contract calls in a secure, efficient, and modular manner.
2. Contract Details
Key Methods:
Owner
execute
: Allows owner to call a specific contract (usually a library or helper contract containing business logic) and pass in encoded function arguments to execute a certain operation.
3. Key Mechanisms & Concepts
Delegate Calls
In the Ethereum smart contract ecosystem, a delegate call is a special type of contract invocation that allows one contract to "borrow" code from another contract, executing it as if it were part of the calling contract's own code. Unlike a regular function call, a delegate call operates within the context of the calling contract, meaning it can read and modify the calling contract's state variables.
4. Gotchas
Dealing with Delegate Calls and ERC20 Transfers
When using proxy contracts that rely on delegate calls, certain common actions like ERC20 token transfers require special handling. In a typical setup, if a user attempts to execute ERC20.transfer
directly, aiming to transfer a balance that is attributed to the proxy, the operation will fail and the call will revert. This is because delegate calls operate in the context of the calling contract, not the called contract. In this case, the calling contract is the proxy, which doesn't hold the tokens, leading to a failed transaction.
To work around this issue, an intermediary contract can be introduced. This intermediary contract is responsible for parsing the intended action and then executing the transfer
operation using a regular call, rather than a delegate call.
5. Failure Modes
Proxy Factory
See HaiProxyFactory.sol and HaiProxyRegistry.sol for more details.
1. Introduction
The Proxy Factory Contract serves as a smart contract template for generating multiple proxy contracts in an automated, scalable manner. The Proxy Registry is a registry that keeps track of all the proxy contracts generated by the Proxy Factory Contract.
2. Contract Details
Key Methods:
Public
build
: Creates a new proxy contract and registers it in the Proxy Registry.
3. Key Mechanisms & Concepts
4. Gotchas
5. Failure Modes
SAFE Manager
See HaiSafeManager.sol and SAFEHandler.sol for more details.
1. Introduction
The SAFE Manager Contract serves as an interface for interacting with the SAFE Engine, which is the core contract responsible for managing SAFEs in the HAI ecosystem. While the SAFE Engine handles the intricate logic and state changes for SAFEs, the SAFE Manager simplifies and streamlines user interactions with their SAFEs. Essentially, it provides an abstraction layer that facilitates operations such as depositing collateral, withdrawing, and managing debt positions in a user-friendly manner.
2. Contract Details
Key Methods:
openSAFE
: Deploys a new SAFE Handler contract and registers it in the SAFE Manager.transferSAFEOwnership
: Initiates the ownership transfer of a SAFE to another address (doesn't reset SAFE protection).acceptSAFEOwnership
: Commits to the ownership transfer of a SAFE to another address (needs to be called by the new SAFE owner).modifySAFECollateralization
: Modifies the collateralization ratio of a SAFE (lock/free collateral and/or generate/repay debt).transferCollateral
: Transfers collateral from one account to another.transferInternalCoins
: Transfers internal coins from one account to another.quitSystem
: Closes a SAFE and transfers all remaining collateral and debt to the user's address.enterSystem
: Migrates collateral and debt from a source SAFE Handler to a destination SAFE.moveSAFE
: Migrates a SAFE from one SAFE to another.protectSAFE
: Protects a SAFE from being liquidated, using a SafeSaviour position to improve the SAFE health when it falls below the liquidation ratio.
3. Key Mechanisms & Concepts
SAFE IDs
The SAFE Engine identifies each SAFE by its unique contract address and the type of collateral it holds. In contrast, the SAFE Manager simplifies this by assigning each SAFE an auto-incremental ID when it is created. This ID serves as an easy-to-use reference point for users and external contracts, streamlining interactions and management. The auto-incremental ID is particularly useful for human readability and ease of interaction, while the address and collateral type identification in the SAFE Engine provides more granularity and is essential for the underlying mechanics.
Understanding the SAFE Handler
The SAFE Handler is a specialized contract that acts as an intermediary between the SAFE Engine and the SAFE Manager in the HAI system. Spawned when a new SAFE is created from the SAFE Manager, this contract communicates directly with the SAFE Engine from its unique address, to grant the SAFE Manager authorization to manage its corresponding SAFE, allowing for simplified user interactions and enhanced security. Essentially, each SAFE Handler represents a single-collateral SAFE and is managed by the SAFE Manager, which also controls any further authorizations for it.
User Authorization
The SAFE Manager Contract allows users to specify which addresses are authorized to interact with their SAFEs. This is crucial for advanced users who may want to deploy automated strategies via external smart contracts or trusted third parties.
SAFE Ownership Transfer
One unique feature is the ability to transfer ownership of a SAFE to another address. This facilitates a range of possibilities, including the sale of debt positions or the use of SAFEs in more complex financial products.
By providing a more accessible interface to the underlying SAFE Engine, the SAFE Manager Contract is an essential tool for anyone looking to interact with SAFEs in the HAI ecosystem.
SAFE Protection
SAFE owners can choose to connect a SafeSaviour position in order to improve the SAFE health and protect it from liquidation. When the SAFE is on the process of being liquidated, the SafeSaviour contract will unwind the user's position, in order to either reduce the SAFE debt, or increase its collateral, to improve the SAFE health and try to prevent liquidation.
SAFE owners need to account that the SafeSaviour position is connected to the SAFE id, so when transferring ownership to another account, it is responsibility of the previous owner to disconnect any liquidity deposited in the SafeSaviour contract.
4. Gotchas
5. Failure Modes
❱ Actions
The Actions Contract streamlines this process by offering a collection of pre-defined "actions" or methods that can be called through a proxy contract. These actions can then be combined into a single, atomic transaction, saving both time and cost.
Basic Actions
See BasicActions.sol for more details.
1. Introduction
These actions encapsulate all functionalities needed for the comprehensive management of Single-Collateral SAFEs within the SAFE Engine. Whether you're aiming to open, modify, or close SAFEs, Basic Actions provide the modular and gas-efficient methods to achieve your goals.
The scope of these Actions is to provide the user with a set of methods to interact with the SAFE Manager Contract. These methods are used by the HAI Proxy contract to execute the corresponding operations on the SAFE Engine.
2. Contract Details
Key Methods:
openSAFE
: Creates a new SAFEHandler (associated with a collateral type) and registers it in the SAFE Manager.generateDebt
: Generates debt within a SAFE and transfers the generated coins to the user's address.lockTokenCollateral
: Locks a certain amount of tokens as collateral within a SAFE.freeTokenCollateral
: Frees a certain amount of tokens from a SAFE's collateral, and transfers them to the user's address.repayAllDebt
: Repays all debt within a SAFE (the amount of debt to repay is automatically calculated).
3. Key Mechanisms & Concepts
Key Concepts for SAFE Management
Managing Single-Collateral SAFEs involves a series of actions to effectively handle your collateral and debt. In this context, four core concepts—Lock, Free, Collect, and Exit—play a pivotal role. These actions are integrated into the Basic Actions module, simplifying the interaction with the SAFE Manager Contract and the SAFE Engine. Here's a closer look at each:
- LOCK: Deposit collateral into a specified SAFE. This effectively "locks" your assets within the SAFE, providing the foundation upon which you can draw debt. It's the starting point for leveraging your assets within the SAFE ecosystem.
- FREE: The inverse of "Lock." It lets you withdraw or "release" collateral from a SAFE back to your designated address, given that you meet the SAFE's conditions (e.g., maintaining a specific collateral ratio).
- COLLECT: The "Collect" action is used to transfer collateral from an external address into the proxy contract. This is generally a preparatory step for other actions, such as "Lock," where the collateral will be moved from the proxy to the SAFE.
- EXIT: The "Exit" action allows you to burn the internal representation of collateral in exchange for ERC20 tokens, which are transferred to your own address. This action is often used when you wish to exit the SAFE ecosystem and convert your assets back to a fungible, transferable form.
4. Gotchas
Internal Balances of the User
In proxy-based systems designed for asset management, the internal balances within the proxy contract are often automatically reset to zero after each transaction. This is because actions are configured to "exit" or transfer any remaining coins or tokens back to the user's own wallet. The design serves dual purposes: it enhances security by not leaving residual assets exposed in the proxy contract, and it simplifies user experience by allowing users to see their complete asset balances directly in their own accounts. Thus, if you observe that the internal balances of your proxy contract are consistently zero, it's because the system is purposefully designed to "exit" any remaining assets, ensuring that no residual value is left lingering within the proxy.
5. Failure Modes
Rewarded Actions
See RewardedActions.sol for more details.
1. Introduction
Maintaining the protocol's overall health often involves executing key maintenance methods. To incentivize these interactions, the Rewarded Actions Contract exists as a specialized layer that batches transactions for interacting with Jobs contracts. These Jobs contracts offer rewards to users for successfully calling specific maintenance methods critical to the protocol. By consolidating these calls into batch transactions via the Rewarded Actions Contract, users can more efficiently earn rewards while aiding in the protocol's upkeep.
2. Contract Details
Key Methods:
startDebtAuction
: Starts a debt auction.startSurplusAction
: Starts a surplus auction.popDebtFromQueue
: Pops a debt block from the Accounting Engine's queue.transferExtraSurplus
: Transfers surplus (instead of auctioning it).liquidateSAFE
: Liquidates a SAFE.updateCollateralPrice
: Fether the latest price for a collateral type to update the system.updateRedemptionRate
: Triggers the redemption rate to be updated.
3. Key Mechanisms & Concepts
Payment Flow
In the HAI ecosystem, when users interact with Jobs contracts for performing key maintenance tasks, the rewards for these actions come from the Stability Fee Treasury. Upon successful execution of a job, the treasury transfers these rewards internally to the user's account within the protocol. Following this, a proxy action is triggered, designed specifically to "burn" these internal coins. This burning process essentially converts the internal balance into ERC20 HAI tokens, which are then withdrawn to the user's external wallet. Thus, the process seamlessly ensures that users are rewarded in a liquid form of HAI tokens that can be freely used or traded.
4. Gotchas
5. Failure Modes
Bidding Actions
See CollateralBidActions.sol, DebtBidActions.sol, SurplusBidActions.sol and PostSettlementSurplusBidActions.sol for more details.
1. Introduction
These contracts serve as the interaction layer between users and the auction houses responsible for handling collateral liquidations, debt auctions, and surplus auctions respectively.
2. Contract Details
Key Methods:
buyCollateral
: Allows users to bid on collateral auctions.decreaseSoldAmount
: Allows users to bid on debt auctions.increaseBidSize
: Allows users to bid on surplus auctions.settleAuction
: Settles an auction and withraws the corresponding funds to the user's account.
3. Key Mechanisms & Concepts
4. Gotchas
5. Failure Modes
Settlement Actions
See GlobalSettlementActions.sol for more details.
1. Introduction
Following a Global Settlement, the Settlement Actions Contract plays a critical role by batching essential transactions needed to interact with the protocol. This contract simplifies user interactions and boosts efficiency by consolidating multiple calls into one, easing the transition to the system's final state. Whether claiming collateral or finalizing debts, the Settlement Actions Contract is the go-to mechanism for all post-settlement activities.
2. Contract Details
Key Methods:
freeCollateral
: Allows users to claim their remaining collateral after a SAFE was processed.prepareCoinsForRedeeming
: Deposits system coins for them to be later redeemed.redeemCollateral
: Claims the corresponding collateral for a given amount of system coins deposited.