💱
StableMaster - Stablecoin Accounting
Maintaining the integrity of a stablecoin
- Contract Name:
StableMasterFront.sol
- ABI:
StableMasterFront.json
26KB
Code
StableMasterFront ABI
StableMaster
is the contract handling all the collateral types accepted for a given stablecoin: there is one such contract per stablecoin of the protocol.It does all the accounting and contains the logic for the fees that are taken to users minting and burning, and for the exchange rate between sanTokens and collateral. This contract is the point of entry in the protocol for stable holders and seekers as well as SLPs.
Besides letting users mint and burn stablecoins as well as SLPs deposit or withdraw collateral, this contract stores for each collateral some accounting quantities like the
stocksUsers
that is the amount of stablecoins that were minted/burnt using this collateral type, or the sanRate
that is the exchange rate between sanTokens and collateral.This contract helps to propagate governance changes across all the contracts of the protocol that have to do with this stablecoin (all the
PoolManager
for instance). It is also at the level of this contract that governance can deploy new collateral types or set new parameters.Although this contract involves collateral
transfer
transactions, collateral, sanTokens or agTokens is never stored on it. When someone sends collateral to the StableMaster
to get stablecoins, this collateral directly goes to the PoolManager
of the associated collateral.Implements
FunctionUtils
, AccessControlUpgradeable
, PausableMapUpgradeable
, IStableMaster
.The contract is upgradeable.
agToken
: Reference to the agToken used in thisStableMaster
_managerList
: List of all the collateral managers, that is thePoolManager
contracts handling the different types of accepted collateral_core
: Reference to theCore
contract of the protocol
Each accepted collateral has its own set of parameters that are specified in a mapping
collateralMap
between the corresponding PoolManager
contract to a struct of references, variables and parameters. References and variables associated to a collateral include:token
: Interface for the token accepted by the underlyingPoolManager
contractsanToken
: Reference to theSanToken
for the poolperpetualManager
: Reference to thePerpetualManager
for the pooloracle
: Address of the oracle for the change rate between collateral and the corresponding stablecoinstocksUsers
: Amount of stablecoins minted using this collateral minus the amount of stablecoins that was burnt while asking for this collateral typesanRate
: Exchange rate between sanTokens and collateralcollatBase
: Base used in the collateral implementationslpData
: Struct containing parameters for SLPs in the protocolfeeData
: Struct containing the fee parameters of the protocol
StableMaster
contracts recognize a collateral from the address of the PoolManager
associated associated to this collateral.lastBlockUpdated
: Last timestamp at which thesanRate
has been updated for SLPs.lockedInterests
: Fees accumulated from previous blocks and to be distributed to SLPsmaxInterestsDistributed
: Max interests used to update thesanRate
in a single block. It should be in collateral token base
The three parameters above are used to prevent front-running/flash-loan attacks for SLPs and to make sure that the
sanRate
does not increase by too much in a small period. Someone seeing that lots of interests are to be distributed to SLPs could for instance take a flash loan, become a SLP, receive the interests and then withdraw its collateral. By not distributing all the fees directly to SLPs and locking some interests, Angle protocol manages to avoid such manipulations.slippage
: Slippage factor that's applied to SLPs exiting (depends on collateral ratio). If it is equal toBASE
, SLPs can get nothing, if this is null, SLPs can get their full claim. The parameter is updated by keepersslippageFee
: Part of the fees normally going to SLPs that is left aside before the protocol is collateralized back again (depends on collateral ratio). Updated by keepersfeesAside
: Amount of fees left aside for SLPs and that will be distributed when the protocol is collateralized back againfeesForSLPs
: Portion of the fees from users minting and burning that goes to SLPsinterestsForSLPs
: Portion of the interests from lending going to SLPs (the rest goes to surplus)
Like everywhere in the protocol, all the fees are scaled by
BASE_PARAMS
:xFeeMint, xFeeBurn
: Values of the thresholds to compute the minting or burning fees depending on HA coverageyFeeMint, yFeeBurn
: Values of the fees at thresholdsbonusMalusMint, bonusMalusBurn
: Minting/Burning fees correction set by theFeeManager
contract depending on the collateral ratio: they are going to be multiplied to the value of the fees computed using the hedge curve. These parameters can either serve as a bonus or as a malus. If thebonusMalus > BASE_PARAMS
, then agents incur a malus and will have larger fees, whilefee < BASE_PARAMS
they incur a smaller fee than what they would have if fees just consisted in what was obtained using coverage.capOnStableMinted
: Parameter used to limit the number of stablecoins that can be issued using the concerned collateral
Only the
CORE_ROLE
, the GOVERNOR_ROLE
and the GUARDIAN_ROLE
are defined in this contract with the Core
being the admin of all roles.As the
StableMaster
needs to be called by FeeManager
and PerpetualManager
, it needs a way to recognize these contracts. The StableMaster
uses a _contractMap
that is a mapping between an address and the PoolManager
contract associated. Using this is cheaper than OpenZeppelin Access Control logic.The following functions are the main points of entry for users to mint and burn stablecoins of the protocol. In each case, either when stablecoins or collateral are involved, users get the possibility to select the beneficiary address of the transaction.
The following functions all have a
poolManager
parameter which specifies the collateral brought or given in return (in the burn
case) . It is hence possible to come and mint agEUR for DAI and redeem USDC from these agEUR.function mint(uint256 amount, address user, IPoolManager poolManager, uint256 minStableAmount) external;
Lets a user add collateral to the system to mint stablecoins. While the collateral involved in the transaction and in a quantity specified by
amount
will always be taken from the msg.sender
, it is possible to have this collateral sent to another address.To check that the
PoolManager
and hence the collateral brought by the user valid, the contract verifies that the collateral associated to it has well a token associated to it in the collateralMap
mapping.Note that it is impossible to mint tokens and to have them sent to the zero address.
Parameters:
amount
: Amount of collateral sentuser
: Address of the contract or the person to give the minted tokens topoolManager
: Address of thePoolManager
of the required collateralminStableAmount
: Minimum amount of stablecoins the user wants to get with this transaction. This serves as a slippage protection for users.
function burn(uint256 amount, address burner, address dest, IPoolManager poolManager, uint256 minCollatAmount) external;
Updates variables to take the burn of agTokens (stablecoins) into account, computes transaction fees and gives collateral from the
PoolManager
in exchange for that.With this function, it is therefore possible to burn stablecoins on behalf of an address (
burner
) and then send the obtained collateral to another dest
address. The msg.sender
should however have approval to burn from the burner
or the msg.sender
should be the burner.
Parameters:
amount
: Amount of stable asset burntburner
: Address from which the agTokens will be burntdest
: Address where collateral is going to bepoolManager
: Collateral type requested by the user burningminCollatAmount
: Minimum amount of collateral requested by the user burning stablecoins. It is a slippage protection for users.
function deposit(uint256 amount, address user, IPoolManager poolManager) external;
Lets a SLP enter the protocol by adding collateral to the system in exchange of sanTokens
Parameters:
user
: Address of the SLP to send sanTokens toamount
: Amount of collateral sentpoolManager
: Address of thePoolManager
of the required collateral
function withdraw(uint256 amount, address burner, address dest, IPoolManager poolManager) external;
Updates variables to account for the burn of sanTokens by a SLP and gives the corresponding collateral back in exchange.
The
msg.sender
should have approval to burn from the burner
or the msg.sender
should be the burner
.Parameters:
amount
: Amount of sanTokens burnt by the SLPburner
: Address that will burn its sanTokensdest
: Address that will receive the collateralpoolManager
: Address of thePoolManager
of the required collateral
function getCollateralRatio() external view returns (uint256);
Returns the collateral ratio for this stablecoin, that is the ratio between the collateral that is controlled by the protocol expressed in stablecoin value and the amount of stablecoins issued.
The following functions are functions that can only be called by other contracts of the protocol. In some cases, the associated collateral is not specified (there is no
poolManager
parameter in the functions). The reason is that the StableMaster
can automatically recognize the caller contract through a _contractMap
.function updateStocksUsers(uint256 amount, address poolManager) external;
This function can only be called by the
agToken
contract. It allows the agToken
contract to update the stocksUsers
for a given collateral after a burn with no redeem.Parameters:
amount
: Amount by whichstocksUsers
should decreasepoolManager
: Reference toPoolManager
for whichstocksUsers
needs to be updated
function accumulateInterest(uint256 gain) external;
Takes into account the gains while lending to strategies and distributes it to SLPs by updating the
sanRate
or locking the interests to be distributed for a short time amount of time before distributing it. This function can only be called by a PoolManager
contract having some strategies associated.Parameters:
gain
: Interests accumulated from lending
function signalLoss(uint256 loss) external;
Takes into account a loss made by a yield farming strategy. This function is called by a
PoolManager
contract having some yield farming strategies associated. Fees are not accumulated for this function before being distributed: everything is directly used to decrease the sanRate.
Parameters:
loss
: Loss made by the yield farming strategy
function setTargetHAHedge(uint256 _targetHAHedge) external;
Sets the proportion of
stocksUsers
available for perpetuals. This function can only be called by the PerpetualManager
: it allows to maintain the consistency between the data in PerpetualManager
and in StableMaster
.function convertToSLP(uint256 amount, address user) external;
Transforms a HA position into a SLP Position. This function can only be called by a
PerpetualManager
contract when a HA wishes to cash out but there is not enough collateral in reserves.Parameters:
amount
: The amount to transformuser
: Address to mint sanTokens to
function getStocksUsers() external returns (uint256);
Transmits to the
PerpetualManager
the max amount HAs can cover.Return Values:
stockUsers
: The amount of stablecoins minted using the collateral corresponding to thePerpetualManager
minus the amount of stablecoins that were burnt for this collateral.
function setFeeKeeper(IPoolManager manager, uint64 _feeMint, uint64 _feeBurn, uint64 _slippage, uint64 _slippageFee) external;
Updates all the fees not depending on personal agents inputs via a keeper calling the corresponding
updateUsersSLPs
function in the FeeManager
contract. This function can hence only be called by an accepted FeeManager
contract.Parameters:
manager
: Reference to thePoolManager
contract corresponding to the collateral of interest_bonusMalusMint
: New corrector of user mint fees for this collateral. These fees will correct the mint fees from users that just depend on the hedge curve by HAs by introducing other dependencies. In normal times they will be equal toBASE_PARAMS
meaning fees will just depend on coverage._bonusMalusBurn
: New corrector of user burn fees, depending on collateral ratio_slippage
: New global slippage (the SLP fees from withdrawing) factor_slippageFee
: New global slippage fee (the non distributed accumulated fees) factor
The
StableMaster
contract contains functions that allow the Core
contract of the protocol handling all the stablecoins to change parameters in the StableMaster
and then to have this contract propagate the changes to the AgToken
contract and to all the collateral managers. The PoolManager
contracts then propagate changes to the contracts of the same pair stablecoin/collateral they are associated to like the PerpetualManager.
These functions include:
addGovernor()
: to add a new governor address to the governor listremoveGovernor()
: to remove an address from the governor listsetGuardian()
: to change the guardian addressrevokeGuardian()
: to revoke the guardian addresssetCore()
: to change the reference to the_core
address of theStableMaster
While some changes can directly be propagated by the
Core
contract, governance has the ability to directly modify some parameters and call some functions in the StableMaster
contract, especially functions regarding a given collateral.function deployCollateral(IPoolManager poolManager, IPerpetualManager perpetualManager, IFeeManager feeManager, IOracle oracle, ISanToken sanToken) external;
Deploys a new collateral by creating the correct references in the corresponding contracts. Some parameters that will then be stored in the
collateralMap
about the deployed collateral can directly be retrieved from the other contracts passed as reference in this function. This is the case for the associated token
which is already stored in the poolManager
contract.Parameters:
poolManager
: Contract managing and storing the deployed collateral for this stablecoinperpetualManager
: Contract managing HA perpetuals for this stablecoin/collateral pairoracle
: Reference to the oracle that will give the price of the collateral with respect to the stablecoinsanToken
: Reference to the sanTokens associated to the collateral
function revokeCollateral(IPoolManager poolManager, ICollateralSettler settlementContract) external;
Removes a collateral from the list of accepted collateral types and pauses all actions associated to this collateral. The reason for this function being only governor is that it has the ability to transfer the contract's funds to another contract.
Before calling this function, governance should make sure that all the collateral lent to strategies has been withdrawn.
Parameters:
poolManager
: Reference to the contract managing this collateral for this stablecoin in the protocolsettlementContract
: Settlement contract that will be used to close everyone's positions and to let users, SLPs and HAs redeem if not all a portion of their claim
function setOracle(IOracle _oracle, IPoolManager poolManager) external;
Propagates the change of oracle for one collateral to all the contracts which need to have the correct oracle reference. This function can only be called by the governor because it could be used to manipulate prices at the advantage of some stakeholders of the protocol while disadvantaging others.
Some parameters may need to be changed rapidly in case of unexpected situations. To this extent, the guardian of the protocol needs to be able to change these parameters. The following functions can only be called by the guardian (or by any other governor address).
function pause(bytes32 agent, IPoolManager poolManager) external;
Pauses an agent's actions within this contract for a given collateral type for this stablecoin
If agent is
STABLE
, it is going to be impossible for users to mint stablecoins using the collateral specified by poolManager
or to burn their stablecoins against the collateral specified by poolManager
. If agent is SLP
, it is going to be impossible for SLPs to deposit the collateral corresponding to poolManager
and receive sanTokens in exchange, or to withdraw the same collateral from their sanTokensParameters:
agent
: Bytes representing the agent (SLP
orSTABLE
) and the collateral type that is going to be paused. To get thebytes32
from a string, we use in Solidity akeccak256
functionpoolManager
: Reference to the contract managing this collateral for this stablecoin in the protocol and for whichagent
needs to be paused
function unpause(bytes32 agent, IPoolManager poolManager) external;
Unpauses an agent's action for a given collateral type for this stablecoin. Before calling this function, the agent should have been paused for this collateral.
Parameters:
agent
: Agent (SLP
orSTABLE
) to unpause the action ofpoolManager
: Reference to the associatedPoolManager
function rebalanceStocksUsers(uint256 amount, IPoolManager poolManagerUp, IPoolManager poolManagerDown) external;
Updates the
stocksUsers
for a given pair of collateral. This function can be called in case where the reserves of the protocol for each collateral do not exactly match what is stored in the stocksUsers
because of increases or decreases in collateral prices at times in which the protocol was not fully covered by HAs.Parameters:
amount
: Amount ofstocksUsers
to transfer from a pool to anotherpoolManagerUp
: Reference toPoolManager
for whichstocksUsers
needs to increasepoolManagerDown
Reference toPoolManager
for whichstocksUsers
needs to decrease
There are many setter functions to change parameters which can only be called by a
GUARDIAN_ROLE
. Each of these functions take a PoolManager
contract as parameter:setUserFees
: Sets the x array (ie thresholds of hedge ratio) and the y array (ie values of fees at thresholds) used to compute mint and burn fees for userssetCapOnStableAndMaxInterests
: Changes the parameters to cap the number of stablecoins you can issue using one collateral type and the maximum interests you can distribute to SLPs in a sanRate update in a blocksetIncentivesForSLPs
: Sets the proportion of fees from burn/mint of users and of lending interests going to SLPs. The higher these proportions the bigger the APY for SLPssetFeeManager
: Sets a newFeeManager
contract for a given collateral and removes the old one which becomes useless