View Source: contracts/TestContracts/TroveManagerBase1MinuteBootstrap.sol
↗ Extends: LiquityBase, TroveManagerStorage
TroveManagerBase1MinuteBootstrap
Enums
enum TroveManagerOperation {
applyPendingRewards,
liquidateInNormalMode,
liquidateInRecoveryMode,
redeemCollateral
}
struct LocalVariables_OuterLiquidationFunction {
uint256 price,
uint256 ZUSDInStabPool,
bool recoveryModeAtStart,
uint256 liquidatedDebt,
uint256 liquidatedColl
}
struct LocalVariables_InnerSingleLiquidateFunction {
uint256 collToLiquidate,
uint256 pendingDebtReward,
uint256 pendingCollReward
}
struct LocalVariables_LiquidationSequence {
uint256 remainingZUSDInStabPool,
uint256 i,
uint256 ICR,
address user,
bool backToNormalMode,
uint256 entireSystemDebt,
uint256 entireSystemColl
}
struct LiquidationValues {
uint256 entireTroveDebt,
uint256 entireTroveColl,
uint256 collGasCompensation,
uint256 ZUSDGasCompensation,
uint256 debtToOffset,
uint256 collToSendToSP,
uint256 debtToRedistribute,
uint256 collToRedistribute,
uint256 collSurplus
}
struct LiquidationTotals {
uint256 totalCollInSequence,
uint256 totalDebtInSequence,
uint256 totalCollGasCompensation,
uint256 totalZUSDGasCompensation,
uint256 totalDebtToOffset,
uint256 totalCollToSendToSP,
uint256 totalDebtToRedistribute,
uint256 totalCollToRedistribute,
uint256 totalCollSurplus
}
struct ContractsCache {
contract IActivePool activePool,
contract IDefaultPool defaultPool,
contract IZUSDToken zusdToken,
contract IZEROStaking zeroStaking,
contract ISortedTroves sortedTroves,
contract ICollSurplusPool collSurplusPool,
address gasPoolAddress
}
struct RedemptionTotals {
uint256 remainingZUSD,
uint256 totalZUSDToRedeem,
uint256 totalETHDrawn,
uint256 ETHFee,
uint256 ETHToSendToRedeemer,
uint256 decayedBaseRate,
uint256 price,
uint256 totalZUSDSupplyAtStart
}
struct SingleRedemptionValues {
uint256 ZUSDLot,
uint256 ETHLot,
bool cancelledPartial
}
Constants & Variables
uint256 public constant SECONDS_IN_ONE_MINUTE;
uint256 public constant MINUTE_DECAY_FACTOR;
uint256 public constant BOOTSTRAP_PERIOD;
uint256 public constant BETA;
Events
event Liquidation(uint256 _liquidatedDebt, uint256 _liquidatedColl, uint256 _collGasCompensation, uint256 _ZUSDGasCompensation);
event Redemption(uint256 _attemptedZUSDAmount, uint256 _actualZUSDAmount, uint256 _ETHSent, uint256 _ETHFee);
event TroveUpdated(address indexed _borrower, uint256 _debt, uint256 _coll, uint256 _stake, enum TroveManagerBase1MinuteBootstrap.TroveManagerOperation _operation);
event TroveLiquidated(address indexed _borrower, uint256 _debt, uint256 _coll, enum TroveManagerBase1MinuteBootstrap.TroveManagerOperation _operation);
event BaseRateUpdated(uint256 _baseRate);
event LastFeeOpTimeUpdated(uint256 _lastFeeOpTime);
event TotalStakesUpdated(uint256 _newTotalStakes);
event SystemSnapshotsUpdated(uint256 _totalStakesSnapshot, uint256 _totalCollateralSnapshot);
event LTermsUpdated(uint256 _L_ETH, uint256 _L_ZUSDDebt);
event TroveSnapshotsUpdated(uint256 _L_ETH, uint256 _L_ZUSDDebt);
event TroveIndexUpdated(address _borrower, uint256 _newIndex);
- _getCurrentICR(address _borrower, uint256 _price)
- _getCurrentTroveAmounts(address _borrower)
- _getPendingETHReward(address _borrower)
- _getPendingZUSDDebtReward(address _borrower)
- _applyPendingRewards(IActivePool _activePool, IDefaultPool _defaultPool, address _borrower)
- _hasPendingRewards(address _borrower)
- _updateTroveRewardSnapshots(address _borrower)
- _movePendingTroveRewardsToActivePool(IActivePool _activePool, IDefaultPool _defaultPool, uint256 _ZUSD, uint256 _ETH)
- _removeStake(address _borrower)
- _closeTrove(address _borrower, enum TroveManagerStorage.Status closedStatus)
- _updateStakeAndTotalStakes(address _borrower)
- _computeNewStake(uint256 _coll)
- _calcDecayedBaseRate()
- _minutesPassedSinceLastFeeOp()
- _updateLastFeeOpTime()
- _calcRedemptionFee(uint256 _redemptionRate, uint256 _ETHDrawn)
- _getRedemptionRate()
- _getRedemptionFee(uint256 _ETHDrawn)
- _calcRedemptionRate(uint256 _baseRate)
- _removeTroveOwner(address _borrower, uint256 TroveOwnersArrayLength)
- _requireCallerIsBorrowerOperations()
- _requireTroveIsActive(address _borrower)
- _requireZUSDBalanceCoversRedemption(IZUSDToken _zusdToken, address _redeemer, uint256 _amount)
- _requireMoreThanOneTroveInSystem(uint256 TroveOwnersArrayLength)
- _requireAmountGreaterThanZero(uint256 _amount)
- _requireTCRoverMCR(uint256 _price)
- _requireAfterBootstrapPeriod()
- _requireValidMaxFeePercentage(uint256 _maxFeePercentage)
function _getCurrentICR(address _borrower, uint256 _price) public view
returns(uint256)
Arguments
Name | Type | Description |
---|---|---|
_borrower | address | |
_price | uint256 |
Source Code
function _getCurrentICR(address _borrower, uint256 _price) public view returns (uint256) {
(uint256 currentETH, uint256 currentZUSDDebt) = _getCurrentTroveAmounts(_borrower);
uint256 ICR = LiquityMath._computeCR(currentETH, currentZUSDDebt, _price);
return ICR;
}
function _getCurrentTroveAmounts(address _borrower) internal view
returns(uint256, uint256)
Arguments
Name | Type | Description |
---|---|---|
_borrower | address |
Source Code
function _getCurrentTroveAmounts(address _borrower) internal view returns (uint256, uint256) {
uint256 pendingETHReward = _getPendingETHReward(_borrower);
uint256 pendingZUSDDebtReward = _getPendingZUSDDebtReward(_borrower);
uint256 currentETH = Troves[_borrower].coll.add(pendingETHReward);
uint256 currentZUSDDebt = Troves[_borrower].debt.add(pendingZUSDDebtReward);
return (currentETH, currentZUSDDebt);
}
function _getPendingETHReward(address _borrower) public view
returns(uint256)
Arguments
Name | Type | Description |
---|---|---|
_borrower | address |
Source Code
function _getPendingETHReward(address _borrower) public view returns (uint256) {
uint256 snapshotETH = rewardSnapshots[_borrower].ETH;
uint256 rewardPerUnitStaked = L_ETH.sub(snapshotETH);
if (rewardPerUnitStaked == 0 || Troves[_borrower].status != Status.active) {
return 0;
}
uint256 stake = Troves[_borrower].stake;
uint256 pendingETHReward = stake.mul(rewardPerUnitStaked).div(DECIMAL_PRECISION);
return pendingETHReward;
}
function _getPendingZUSDDebtReward(address _borrower) public view
returns(uint256)
Arguments
Name | Type | Description |
---|---|---|
_borrower | address |
Source Code
function _getPendingZUSDDebtReward(address _borrower) public view returns (uint256) {
uint256 snapshotZUSDDebt = rewardSnapshots[_borrower].ZUSDDebt;
uint256 rewardPerUnitStaked = L_ZUSDDebt.sub(snapshotZUSDDebt);
if (rewardPerUnitStaked == 0 || Troves[_borrower].status != Status.active) {
return 0;
}
uint256 stake = Troves[_borrower].stake;
uint256 pendingZUSDDebtReward = stake.mul(rewardPerUnitStaked).div(DECIMAL_PRECISION);
return pendingZUSDDebtReward;
}
function _applyPendingRewards(IActivePool _activePool, IDefaultPool _defaultPool, address _borrower) internal nonpayable
Arguments
Name | Type | Description |
---|---|---|
_activePool | IActivePool | |
_defaultPool | IDefaultPool | |
_borrower | address |
Source Code
function _applyPendingRewards(
IActivePool _activePool,
IDefaultPool _defaultPool,
address _borrower
) internal {
if (_hasPendingRewards(_borrower)) {
_requireTroveIsActive(_borrower);
// Compute pending rewards
uint256 pendingETHReward = _getPendingETHReward(_borrower);
uint256 pendingZUSDDebtReward = _getPendingZUSDDebtReward(_borrower);
// Apply pending rewards to trove's state
Troves[_borrower].coll = Troves[_borrower].coll.add(pendingETHReward);
Troves[_borrower].debt = Troves[_borrower].debt.add(pendingZUSDDebtReward);
_updateTroveRewardSnapshots(_borrower);
// Transfer from DefaultPool to ActivePool
_movePendingTroveRewardsToActivePool(
_activePool,
_defaultPool,
pendingZUSDDebtReward,
pendingETHReward
);
emit TroveUpdated(
_borrower,
Troves[_borrower].debt,
Troves[_borrower].coll,
Troves[_borrower].stake,
TroveManagerOperation.applyPendingRewards
);
}
}
function _hasPendingRewards(address _borrower) public view
returns(bool)
Arguments
Name | Type | Description |
---|---|---|
_borrower | address |
Source Code
function _hasPendingRewards(address _borrower) public view returns (bool) {
/*
* A Trove has pending rewards if its snapshot is less than the current rewards per-unit-staked sum:
* this indicates that rewards have occured since the snapshot was made, and the user therefore has
* pending rewards
*/
if (Troves[_borrower].status != Status.active) {
return false;
}
return (rewardSnapshots[_borrower].ETH < L_ETH);
}
function _updateTroveRewardSnapshots(address _borrower) internal nonpayable
Arguments
Name | Type | Description |
---|---|---|
_borrower | address |
Source Code
function _updateTroveRewardSnapshots(address _borrower) internal {
rewardSnapshots[_borrower].ETH = L_ETH;
rewardSnapshots[_borrower].ZUSDDebt = L_ZUSDDebt;
emit TroveSnapshotsUpdated(L_ETH, L_ZUSDDebt);
}
function _movePendingTroveRewardsToActivePool(IActivePool _activePool, IDefaultPool _defaultPool, uint256 _ZUSD, uint256 _ETH) internal nonpayable
Arguments
Name | Type | Description |
---|---|---|
_activePool | IActivePool | |
_defaultPool | IDefaultPool | |
_ZUSD | uint256 | |
_ETH | uint256 |
Source Code
function _movePendingTroveRewardsToActivePool(
IActivePool _activePool,
IDefaultPool _defaultPool,
uint256 _ZUSD,
uint256 _ETH
) internal {
_defaultPool.decreaseZUSDDebt(_ZUSD);
_activePool.increaseZUSDDebt(_ZUSD);
_defaultPool.sendETHToActivePool(_ETH);
}
function _removeStake(address _borrower) internal nonpayable
Arguments
Name | Type | Description |
---|---|---|
_borrower | address |
Source Code
function _removeStake(address _borrower) internal {
uint256 stake = Troves[_borrower].stake;
totalStakes = totalStakes.sub(stake);
Troves[_borrower].stake = 0;
}
function _closeTrove(address _borrower, enum TroveManagerStorage.Status closedStatus) internal nonpayable
Arguments
Name | Type | Description |
---|---|---|
_borrower | address | |
closedStatus | enum TroveManagerStorage.Status |
Source Code
function _closeTrove(address _borrower, Status closedStatus) internal {
assert(closedStatus != Status.nonExistent && closedStatus != Status.active);
uint256 TroveOwnersArrayLength = TroveOwners.length;
_requireMoreThanOneTroveInSystem(TroveOwnersArrayLength);
Troves[_borrower].status = closedStatus;
Troves[_borrower].coll = 0;
Troves[_borrower].debt = 0;
rewardSnapshots[_borrower].ETH = 0;
rewardSnapshots[_borrower].ZUSDDebt = 0;
_removeTroveOwner(_borrower, TroveOwnersArrayLength);
sortedTroves.remove(_borrower);
}
function _updateStakeAndTotalStakes(address _borrower) internal nonpayable
returns(uint256)
Arguments
Name | Type | Description |
---|---|---|
_borrower | address |
Source Code
function _updateStakeAndTotalStakes(address _borrower) internal returns (uint256) {
uint256 newStake = _computeNewStake(Troves[_borrower].coll);
uint256 oldStake = Troves[_borrower].stake;
Troves[_borrower].stake = newStake;
totalStakes = totalStakes.sub(oldStake).add(newStake);
emit TotalStakesUpdated(totalStakes);
return newStake;
}
function _computeNewStake(uint256 _coll) internal view
returns(uint256)
Arguments
Name | Type | Description |
---|---|---|
_coll | uint256 |
Source Code
function _computeNewStake(uint256 _coll) internal view returns (uint256) {
uint256 stake;
if (totalCollateralSnapshot == 0) {
stake = _coll;
} else {
/*
* The following assert() holds true because:
* - The system always contains >= 1 trove
* - When we close or liquidate a trove, we redistribute the pending rewards, so if all troves were closed/liquidated,
* rewards would’ve been emptied and totalCollateralSnapshot would be zero too.
*/
assert(totalStakesSnapshot > 0);
stake = _coll.mul(totalStakesSnapshot).div(totalCollateralSnapshot);
}
return stake;
}
function _calcDecayedBaseRate() internal view
returns(uint256)
Source Code
nction _calcDecayedBaseRate() internal view returns (uint256) {
uint256 minutesPassed = _minutesPassedSinceLastFeeOp();
uint256 decayFactor = LiquityMath._decPow(MINUTE_DECAY_FACTOR, minutesPassed);
return baseRate.mul(decayFactor).div(DECIMAL_PRECISION);
}
function _minutesPassedSinceLastFeeOp() internal view
returns(uint256)
Source Code
nction _minutesPassedSinceLastFeeOp() internal view returns (uint256) {
return (block.timestamp.sub(lastFeeOperationTime)).div(SECONDS_IN_ONE_MINUTE);
}
function _updateLastFeeOpTime() internal nonpayable
Source Code
nction _updateLastFeeOpTime() internal {
uint256 timePassed = block.timestamp.sub(lastFeeOperationTime);
if (timePassed >= SECONDS_IN_ONE_MINUTE) {
lastFeeOperationTime = block.timestamp;
emit LastFeeOpTimeUpdated(block.timestamp);
}
}
function _calcRedemptionFee(uint256 _redemptionRate, uint256 _ETHDrawn) internal pure
returns(uint256)
Arguments
Name | Type | Description |
---|---|---|
_redemptionRate | uint256 | |
_ETHDrawn | uint256 |
Source Code
nction _calcRedemptionFee(uint256 _redemptionRate, uint256 _ETHDrawn)
internal
pure
returns (uint256)
{
uint256 redemptionFee = _redemptionRate.mul(_ETHDrawn).div(DECIMAL_PRECISION);
require(redemptionFee < _ETHDrawn, "TroveManager: Fee would eat up all returned collateral");
return redemptionFee;
}
function _getRedemptionRate() public view
returns(uint256)
Source Code
nction _getRedemptionRate() public view returns (uint256) {
return _calcRedemptionRate(baseRate);
}
function _getRedemptionFee(uint256 _ETHDrawn) internal view
returns(uint256)
Arguments
Name | Type | Description |
---|---|---|
_ETHDrawn | uint256 |
Source Code
nction _getRedemptionFee(uint256 _ETHDrawn) internal view returns (uint256) {
return _calcRedemptionFee(_getRedemptionRate(), _ETHDrawn);
}
function _calcRedemptionRate(uint256 _baseRate) internal view
returns(uint256)
Arguments
Name | Type | Description |
---|---|---|
_baseRate | uint256 |
Source Code
nction _calcRedemptionRate(uint256 _baseRate) internal view returns (uint256) {
return
LiquityMath._min(
liquityBaseParams.REDEMPTION_FEE_FLOOR().add(_baseRate),
DECIMAL_PRECISION // cap at a maximum of 100%
);
}
function _removeTroveOwner(address _borrower, uint256 TroveOwnersArrayLength) internal nonpayable
Arguments
Name | Type | Description |
---|---|---|
_borrower | address | |
TroveOwnersArrayLength | uint256 |
Source Code
nction _removeTroveOwner(address _borrower, uint256 TroveOwnersArrayLength) internal {
Status troveStatus = Troves[_borrower].status;
// It’s set in caller function `_closeTrove`
assert(troveStatus != Status.nonExistent && troveStatus != Status.active);
uint128 index = Troves[_borrower].arrayIndex;
uint256 length = TroveOwnersArrayLength;
uint256 idxLast = length.sub(1);
assert(index <= idxLast);
address addressToMove = TroveOwners[idxLast];
TroveOwners[index] = addressToMove;
Troves[addressToMove].arrayIndex = index;
emit TroveIndexUpdated(addressToMove, index);
TroveOwners.pop();
}
function _requireCallerIsBorrowerOperations() internal view
Source Code
tion _requireCallerIsBorrowerOperations() internal view {
require(
msg.sender == borrowerOperationsAddress,
"TroveManager: Caller is not the BorrowerOperations contract"
);
}
function _requireTroveIsActive(address _borrower) internal view
Arguments
Name | Type | Description |
---|---|---|
_borrower | address |
Source Code
tion _requireTroveIsActive(address _borrower) internal view {
require(
Troves[_borrower].status == Status.active,
"TroveManager: Trove does not exist or is closed"
);
}
function _requireZUSDBalanceCoversRedemption(IZUSDToken _zusdToken, address _redeemer, uint256 _amount) internal view
Arguments
Name | Type | Description |
---|---|---|
_zusdToken | IZUSDToken | |
_redeemer | address | |
_amount | uint256 |
Source Code
tion _requireZUSDBalanceCoversRedemption(
IZUSDToken _zusdToken,
address _redeemer,
uint256 _amount
) internal view {
require(
_zusdToken.balanceOf(_redeemer) >= _amount,
"TroveManager: Requested redemption amount must be <= user's ZUSD token balance"
);
}
function _requireMoreThanOneTroveInSystem(uint256 TroveOwnersArrayLength) internal view
Arguments
Name | Type | Description |
---|---|---|
TroveOwnersArrayLength | uint256 |
Source Code
tion _requireMoreThanOneTroveInSystem(uint256 TroveOwnersArrayLength) internal view {
require(
TroveOwnersArrayLength > 1 && sortedTroves.getSize() > 1,
"TroveManager: Only one trove in the system"
);
}
function _requireAmountGreaterThanZero(uint256 _amount) internal pure
Arguments
Name | Type | Description |
---|---|---|
_amount | uint256 |
Source Code
tion _requireAmountGreaterThanZero(uint256 _amount) internal pure {
require(_amount > 0, "TroveManager: Amount must be greater than zero");
}
function _requireTCRoverMCR(uint256 _price) internal view
Arguments
Name | Type | Description |
---|---|---|
_price | uint256 |
Source Code
tion _requireTCRoverMCR(uint256 _price) internal view {
require(
_getTCR(_price) >= liquityBaseParams.MCR(),
"TroveManager: Cannot redeem when TCR < MCR"
);
}
function _requireAfterBootstrapPeriod() internal view
Source Code
tion _requireAfterBootstrapPeriod() internal view {
uint256 systemDeploymentTime = _zeroToken.getDeploymentStartTime();
require(
block.timestamp >= systemDeploymentTime.add(BOOTSTRAP_PERIOD),
"TroveManager: Redemptions are not allowed during bootstrap phase"
);
}
function _requireValidMaxFeePercentage(uint256 _maxFeePercentage) internal view
Arguments
Name | Type | Description |
---|---|---|
_maxFeePercentage | uint256 |
Source Code
tion _requireValidMaxFeePercentage(uint256 _maxFeePercentage) internal view {
require(
_maxFeePercentage >= liquityBaseParams.REDEMPTION_FEE_FLOOR() &&
_maxFeePercentage <= DECIMAL_PRECISION,
"Max fee percentage must be between 0.5% and 100%"
);
}
}
- ActivePool
- ActivePoolStorage
- BaseMath
- BorrowerOperations
- BorrowerOperationsScript
- BorrowerOperationsStorage
- BorrowerWrappersScript
- CheckContract
- CollSurplusPool
- CollSurplusPoolStorage
- console
- Context
- DefaultPool
- DefaultPoolStorage
- DocsCover
- DSAuth
- DSAuthEvents
- DSAuthority
- DSNote
- DSProxy
- DSProxyCache
- DSProxyFactory
- ERC20
- ETHTransferScript
- FeeDistributor
- FeeDistributorStorage
- GasPool
- HintHelpers
- HintHelpersStorage
- IActivePool
- IBalanceRedirectPresale
- IBorrowerOperations
- ICollSurplusPool
- IDefaultPool
- IERC20
- IERC2612
- IExternalPriceFeed
- IFeeDistributor
- IFeeSharingProxy
- ILiquityBase
- ILiquityBaseParams
- IMasset
- IMoCBaseOracle
- Initializable
- IPool
- IPriceFeed
- IRSKOracle
- ISortedTroves
- IStabilityPool
- ITroveManager
- IWrbtc
- IZUSDToken
- LiquityBase
- LiquityBaseParams
- LiquityMath
- LiquitySafeMath128
- MoCMedianizer
- MultiTroveGetter
- MultiTroveGetterStorage
- NueToken
- Ownable
- PriceFeed
- PriceFeedStorage
- ProxiableContract
- ProxiableContract2
- Proxy
- RskOracle
- SafeMath
- SortedTroves
- SortedTrovesStorage
- StabilityPool
- StabilityPoolScript
- StabilityPoolStorage
- Storage
- Storage2
- TokenScript
- TroveManager
- TroveManagerBase
- TroveManagerBase1MinuteBootstrap
- TroveManagerRedeemOps
- TroveManagerScript
- TroveManagerStorage
- UpgradableProxy
- ZUSDToken
- ZUSDTokenStorage