View Source: contracts/modules/LoanClosingsLiquidation.sol
↗ Extends: LoanClosingsShared, LiquidationHelper
Ways to close a loan: liquidation. Margin trade positions are always closed with a swap.
- Loans are liquidated if the position goes below margin maintenance.
Constants & Variables
uint256 internal constant MONTH;
- constructor()
- constructor()
- initialize(address target)
- liquidate(bytes32 loanId, address receiver, uint256 closeAmount)
- _liquidate(bytes32 loanId, address receiver, uint256 closeAmount)
- _swapBackExcess(struct LoanStruct.Loan loanLocal, struct LoanParamsStruct.LoanParams loanParamsLocal, uint256 swapAmount, bytes loanDataBytes)
function () public nonpayable
Source Code
constructor() public {}
function () external nonpayable
Source Code
function() external {
revert("fallback not allowed");
}
function initialize(address target) external nonpayable onlyOwner
Arguments
Name | Type | Description |
---|---|---|
target | address |
Source Code
function initialize(address target) external onlyOwner {
address prevModuleContractAddress = logicTargets[this.liquidate.selector];
_setTarget(this.liquidate.selector, target);
emit ProtocolModuleContractReplaced(
prevModuleContractAddress,
target,
"LoanClosingsLiquidation"
);
}
Liquidate an unhealty loan. *
function liquidate(bytes32 loanId, address receiver, uint256 closeAmount) external payable nonReentrant globallyNonReentrant iTokenSupplyUnchanged whenNotPaused
returns(loanCloseAmount uint256, seizedAmount uint256, seizedToken address)
Arguments
Name | Type | Description |
---|---|---|
loanId | bytes32 | The ID of the loan to liquidate. loanId is the ID of the loan, which is created on loan opening. It can be obtained either by parsing the Trade event or by reading the open loans from the contract by calling getActiveLoans or getUserLoans. |
receiver | address | The receiver of the seized amount. |
closeAmount | uint256 | The amount to close in loanTokens. * |
Returns
loanCloseAmount The amount of the collateral token of the loan.
Source Code
function liquidate(
bytes32 loanId,
address receiver,
uint256 closeAmount // denominated in loanToken
)
external
payable
nonReentrant
globallyNonReentrant
iTokenSupplyUnchanged(loanId)
whenNotPaused
returns (
uint256 loanCloseAmount,
uint256 seizedAmount,
address seizedToken
)
{
return _liquidate(loanId, receiver, closeAmount);
}
Internal function for liquidating an unhealthy loan. * The caller needs to approve the closeAmount prior to calling. Will not liquidate more than is needed to restore the desired margin (maintenance +5%). * Whenever the current margin of a loan falls below maintenance margin, it needs to be liquidated. Anybody can initiate a liquidation and buy the collateral tokens at a discounted rate (5%). *
function _liquidate(bytes32 loanId, address receiver, uint256 closeAmount) internal nonpayable
returns(loanCloseAmount uint256, seizedAmount uint256, seizedToken address)
Arguments
Name | Type | Description |
---|---|---|
loanId | bytes32 | The ID of the loan to liquidate. |
receiver | address | The receiver of the seized amount. |
closeAmount | uint256 | The amount to close in loanTokens. * |
Returns
loanCloseAmount The amount of the collateral token of the loan.
Source Code
function _liquidate(
bytes32 loanId,
address receiver,
uint256 closeAmount
)
internal
returns (
uint256 loanCloseAmount,
uint256 seizedAmount,
address seizedToken
)
{
(Loan storage loanLocal, LoanParams storage loanParamsLocal) = _checkLoan(loanId);
(uint256 currentMargin, uint256 collateralToLoanRate) =
IPriceFeeds(priceFeeds).getCurrentMargin(
loanParamsLocal.loanToken,
loanParamsLocal.collateralToken,
loanLocal.principal,
loanLocal.collateral
);
require(currentMargin <= loanParamsLocal.maintenanceMargin, "healthy position");
loanCloseAmount = closeAmount;
//amounts to restore the desired margin (maintencance + 5%)
(uint256 maxLiquidatable, uint256 maxSeizable, ) =
_getLiquidationAmounts(
loanLocal.principal,
loanLocal.collateral,
currentMargin,
loanParamsLocal.maintenanceMargin,
collateralToLoanRate
);
if (loanCloseAmount < maxLiquidatable) {
//close maxLiquidatable if tiny position will remain
uint256 remainingAmount = maxLiquidatable - loanCloseAmount;
remainingAmount = _getAmountInRbtc(loanParamsLocal.loanToken, remainingAmount);
if (remainingAmount <= TINY_AMOUNT) {
loanCloseAmount = maxLiquidatable;
seizedAmount = maxSeizable;
} else {
seizedAmount = maxSeizable.mul(loanCloseAmount).div(maxLiquidatable);
}
} else if (loanCloseAmount > maxLiquidatable) {
// adjust down the close amount to the max
loanCloseAmount = maxLiquidatable;
seizedAmount = maxSeizable;
} else {
seizedAmount = maxSeizable;
}
require(loanCloseAmount != 0, "nothing to liquidate");
// liquidator deposits the principal being closed
_returnPrincipalWithDeposit(loanParamsLocal.loanToken, address(this), loanCloseAmount);
// a portion of the principal is repaid to the lender out of interest refunded
uint256 loanCloseAmountLessInterest =
_settleInterestToPrincipal(
loanLocal,
loanParamsLocal,
loanCloseAmount,
loanLocal.borrower
);
if (loanCloseAmount > loanCloseAmountLessInterest) {
// full interest refund goes to the borrower
_withdrawAsset(
loanParamsLocal.loanToken,
loanLocal.borrower,
loanCloseAmount - loanCloseAmountLessInterest
);
}
if (loanCloseAmountLessInterest != 0) {
// The lender always gets back an ERC20 (even wrbtc), so we call withdraw directly rather than
// use the _withdrawAsset helper function
vaultWithdraw(
loanParamsLocal.loanToken,
loanLocal.lender,
loanCloseAmountLessInterest
);
}
seizedToken = loanParamsLocal.collateralToken;
if (seizedAmount != 0) {
loanLocal.collateral = loanLocal.collateral.sub(seizedAmount);
_withdrawAsset(seizedToken, receiver, seizedAmount);
}
_closeLoan(loanLocal, loanCloseAmount);
_emitClosingEvents(
loanParamsLocal,
loanLocal,
loanCloseAmount,
seizedAmount,
collateralToLoanRate,
0,
currentMargin,
CloseTypes.Liquidation
);
}
Swap back excessive loan tokens to collateral tokens. *
function _swapBackExcess(struct LoanStruct.Loan loanLocal, struct LoanParamsStruct.LoanParams loanParamsLocal, uint256 swapAmount, bytes loanDataBytes) internal nonpayable
returns(destTokenAmountReceived uint256, sourceTokenAmountUsed uint256, collateralToLoanSwapRate uint256)
Arguments
Name | Type | Description |
---|---|---|
loanLocal | struct LoanStruct.Loan | The loan object. |
loanParamsLocal | struct LoanParamsStruct.LoanParams | The loan parameters. |
swapAmount | uint256 | The amount to be swapped. |
loanDataBytes | bytes | Additional loan data (not in use for token swaps). * |
Returns
destTokenAmountReceived The amount of destiny tokens received.
Source Code
function _swapBackExcess(
Loan memory loanLocal,
LoanParams memory loanParamsLocal,
uint256 swapAmount,
bytes memory loanDataBytes
)
internal
returns (
uint256 destTokenAmountReceived,
uint256 sourceTokenAmountUsed,
uint256 collateralToLoanSwapRate
)
{
(destTokenAmountReceived, sourceTokenAmountUsed, collateralToLoanSwapRate) = _loanSwap(
loanLocal.id,
loanParamsLocal.loanToken,
loanParamsLocal.collateralToken,
loanLocal.borrower,
swapAmount, // minSourceTokenAmount
swapAmount, // maxSourceTokenAmount
0, // requiredDestTokenAmount
false, // bypassFee
loanDataBytes
);
require(sourceTokenAmountUsed <= swapAmount, "excessive source amount");
}
- Address
- Administered
- AdminRole
- AdvancedToken
- AdvancedTokenStorage
- Affiliates
- AffiliatesEvents
- ApprovalReceiver
- BProPriceFeed
- CheckpointsShared
- Constants
- Context
- DevelopmentFund
- DummyContract
- EnumerableAddressSet
- EnumerableBytes32Set
- EnumerableBytes4Set
- ERC20
- ERC20Detailed
- ErrorDecoder
- Escrow
- EscrowReward
- FeedsLike
- FeesEvents
- FeeSharingCollector
- FeeSharingCollectorProxy
- FeeSharingCollectorStorage
- FeesHelper
- FourYearVesting
- FourYearVestingFactory
- FourYearVestingLogic
- FourYearVestingStorage
- GenericTokenSender
- GovernorAlpha
- GovernorVault
- IApproveAndCall
- IChai
- IContractRegistry
- IConverterAMM
- IERC1820Registry
- IERC20_
- IERC20
- IERC777
- IERC777Recipient
- IERC777Sender
- IFeeSharingCollector
- IFourYearVesting
- IFourYearVestingFactory
- IFunctionsList
- ILiquidityMining
- ILiquidityPoolV1Converter
- ILoanPool
- ILoanToken
- ILoanTokenLogicBeacon
- ILoanTokenLogicModules
- ILoanTokenLogicProxy
- ILoanTokenModules
- ILoanTokenWRBTC
- ILockedSOV
- IMoCState
- IModulesProxyRegistry
- Initializable
- InterestUser
- IPot
- IPriceFeeds
- IPriceFeedsExt
- IProtocol
- IRSKOracle
- ISovryn
- ISovrynSwapNetwork
- IStaking
- ISwapsImpl
- ITeamVesting
- ITimelock
- IV1PoolOracle
- IVesting
- IVestingFactory
- IVestingRegistry
- IWrbtc
- IWrbtcERC20
- LenderInterestStruct
- LiquidationHelper
- LiquidityMining
- LiquidityMiningConfigToken
- LiquidityMiningProxy
- LiquidityMiningStorage
- LoanClosingsEvents
- LoanClosingsLiquidation
- LoanClosingsRollover
- LoanClosingsShared
- LoanClosingsWith
- LoanClosingsWithoutInvariantCheck
- LoanInterestStruct
- LoanMaintenance
- LoanMaintenanceEvents
- LoanOpenings
- LoanOpeningsEvents
- LoanParamsStruct
- LoanSettings
- LoanSettingsEvents
- LoanStruct
- LoanToken
- LoanTokenBase
- LoanTokenLogicBeacon
- LoanTokenLogicLM
- LoanTokenLogicProxy
- LoanTokenLogicStandard
- LoanTokenLogicStorage
- LoanTokenLogicWrbtc
- LoanTokenSettingsLowerAdmin
- LockedSOV
- MarginTradeStructHelpers
- Medianizer
- ModuleCommonFunctionalities
- ModulesCommonEvents
- ModulesProxy
- ModulesProxyRegistry
- MultiSigKeyHolders
- MultiSigWallet
- Mutex
- Objects
- OrderStruct
- OrigingVestingCreator
- OriginInvestorsClaim
- Ownable
- Pausable
- PausableOz
- PreviousLoanToken
- PreviousLoanTokenSettingsLowerAdmin
- PriceFeedRSKOracle
- PriceFeeds
- PriceFeedsLocal
- PriceFeedsMoC
- PriceFeedV1PoolOracle
- ProtocolAffiliatesInterface
- ProtocolLike
- ProtocolSettings
- ProtocolSettingsEvents
- ProtocolSettingsLike
- ProtocolSwapExternalInterface
- ProtocolTokenUser
- Proxy
- ProxyOwnable
- ReentrancyGuard
- RewardHelper
- RSKAddrValidator
- SafeERC20
- SafeMath
- SafeMath96
- setGet
- SharedReentrancyGuard
- SignedSafeMath
- SOV
- sovrynProtocol
- StakingAdminModule
- StakingGovernanceModule
- StakingInterface
- StakingProxy
- StakingRewards
- StakingRewardsProxy
- StakingRewardsStorage
- StakingShared
- StakingStakeModule
- StakingStorageModule
- StakingStorageShared
- StakingVestingModule
- StakingWithdrawModule
- State
- SwapsEvents
- SwapsExternal
- SwapsImplLocal
- SwapsImplSovrynSwap
- SwapsUser
- TeamVesting
- Timelock
- TimelockHarness
- TimelockInterface
- TokenSender
- UpgradableProxy
- USDTPriceFeed
- Utils
- VaultController
- Vesting
- VestingCreator
- VestingFactory
- VestingLogic
- VestingRegistry
- VestingRegistry2
- VestingRegistry3
- VestingRegistryLogic
- VestingRegistryProxy
- VestingRegistryStorage
- VestingStorage
- WeightedStakingModule
- WRBTC