Note that the ExpiringMultiParty code simply inherits Liquidatable and adds no additional functionality. Therefore, these two names essentially describe the same thing. All of the code can be viewed in Liquidatable.

How Liquidations Work

If a sponsor is holding a synthetic asset position that Alice believes is undercollateralized, she can start a liquidation for this position by calling createLiquidation (see below). A liquidation can target the entire position or just a part of it; this is determined by how much synthetic asset Alice transfers during the call (set by maxTokensToLiquidate). Alice must also include ooReward collateral to pay for the Optimistic Oracle’s price request in the case of a dispute (but she gets this back if there is no dispute or if the dispute is ruled in her favour). Note that as soon as a liquidation has begun in this way, the position is immediately reduced for the amount of the liquidation; even if it’s ultimately successfully disputed the position will be reduced (or removed); in that case, the holder of the position would be compensated with any excess collateral of the liquidated portion, as well as a reward that scales with the size of the liquidation based on sponsorDisputeRewardPercentage (see below). The liquidation stays open to disputes for a time period called liquidationLiveness. If no disputes come in during this time, the contract “optimistically” assumes Alice was correct. Alice would then receive a proportional amount of collateral from the position: if she had submitted 50% of the position.tokensOutstanding debt, she would receive 50% of the collateral in the position. As a natural consequence, the higher the collateralRequirement is, the more rewarded Alice is: if 1.5 (aka 150%), Alice would have essentially traded in the synthetic token for 150% of its value in the collateral token (this assumes the position was only barely undercollateralized). She could then of course trade this on the open market and return with more of the synthetic asset to perform more liquidations if there were still any liquidatable positions. Anyone who can pay the disputer bond and their own ooReward can dispute this liquidation, before liquidationLiveness has passed. Disputing triggers a price request for the asset from UMA’s OptimisticOracle, which uses priceIdentifier and ancillaryData to determine which asset to price and how to price it. withdrawLiquidation can be called either when liquidationLiveness has passed without any disputes, or once the OptimisticOracle has a price available for a dispute’s price request. This function settles a dispute if there is one by comparing the price to the position’s balances, and sends out rewards to various parties (disputer, liquidator, sponsor).

Interaction with “Slow Withdrawals”

The behaviour of liquidations and slow withdrawals (see requestWithdrawal from 2. PricelessPositionManager) interrelate in a few ways.

  • Any slow withdrawal is also reduced by the same proportion the position was reduced by, as a result of starting the liquidation.

  • Upon dispute, the position health is determined after taking into account any pending slow withdrawals, as if they have already gone through. Thus a position that is undergoing a slow withdrawal for most of its collateral is more likely to be ruled insolvent and punished. This allows liquidators to react to slow withdrawals which, unlike fast withdrawals, are not limited to the amount of collateral they can withdraw.

  • Liquidations over the “griefing threshold” (currently arbitrarily set to minSponsorPosition) cause the countdown timer on withdrawals to reset. The purpose of this behaviour is to allow liquidators time to gather funds and liquidate chunks of a position that’s undergoing massive withdrawals while preventing small “troll” liquidations to be able to trigger this timer reset.

State Variables

liquidations contains, for each sponsor address, an array of LiquidationData objects. When a liquidation is created, a LiquidataionData object is appended to the array of liquidations for that sponsor. These objects track the lifetime of a liquidation, through any possible dispute, and are zeroed out when the liquidation resolves one way or another. Some of these members are clear enough from the code/comments; here are some helpful comments for the rest:

  • state simply tracks the state in a Status enum. Any active liquidation will never actually be in the Uninitializedstate.

  • liquidationTime is the timestamp of when the liquidation started. This timestamp is also used when sending price requests to the optimistic oracle for any possible disputes. It’s the price “at this time” that is the subject of this liquidation.

  • tokensOutstanding and lockedCollateral represent how much of the position is being liquidated, in terms of synthetic token debt and collateral, respectively.

  • lockedCollateralAfterWithdrawals: The amount of collateral that would be locked in the liquidation if all pending slow withdrawals went through. The sole purpose of this variable is to be used during disputes: by considering the amount of collateral a position will have after withdrawals go through, liquidations can occur for positions that attempt to withdraw so much that their CR would go below collateralRequirement.

  • finalFee: The liquidator and disputer must each include this as a bond. If there is no dispute, the liquidator gets this back. If there is a dispute, then the contract will have received finalFee*2 in total. finalFee is sent along to the oracle as a reward, and finalFee whoever wins the dispute (liquidator or disputer) gets finalFee back.

liquidationCollateral stores the total amount of collateral in all liquidations; liquidationCollateral + totalPositionCollateral should always equal the sum of all actual collateral held in the EMP contract.

Immutable (set at construction) Variables

liquidationLiveness is the minimum amount of time a liquidation stays open for dispute. If no dispute occurs before this time, the liquidator can withdraw the liquidation, and no call to the optimistic oracle is made. collateralRequirement is the ratio of collateralization under which a position can be legitimately liquidated. In contrast to the GCR described in PricelessPositionManager, this ratio is ultimately calculated with the worth of the synthetic token debt versus the collateral held (during a dispute, when the price is available). If this value is set to 1.25, this means that any position that has less than 125% of the debt value deposited as collateral, can be legitimately liquidated by liquidators. The next three variables are all expressed as a FixedPoint decimal, where i.e. 0.1 indicates 10%. disputeBondPercentage determines the amount the disputer has to put up as a bond, as a percentage of the liquidations lockedCollateral. Note that this is not the only fee the disputer has to pay; see finalFee above in the LiquidationData struct. sponsorDisputeRewardPercentage: In the case of a successful dispute, this is the reward paid to the sponsor (whose position has just been liquidated), expressed as a percentage of the amount that was under liquidation. disputerDisputeRewardPercentage: In the case of a successful dispute, this is the reward paid to the disputer, expressed as a percentage of the amount that was under liquidation.

External/Public State-Changing Functions

createLiquidation starts a liquidation claim on any sponsor’s position. The sender must provide some amount of the synthetic asset (maxTokensToLiquidate) as well as ooReward collateral as a bond that will get refunded except in the case of a successful dispute. The next two arguments, minCollateralPerToken and maxCollateralPerToken dictate a max and min value for the ratio of collateral the liquidator expects to get back, for each of the synthetic tokens provided (specified in FixedPoint decimals; i.e. 10^18 = 1.0). The last argument specifies a deadline after which the transaction will fail. All of these last three arguments are guards built for the convenience of the caller, to dictate under which terms he is willing to initiate the liquidation. dispute can be called on any open liquidation. The caller must supply collateral equal to (disputeBondPercentage * position.lockedCollateral) + ooReward, both of which are returned (plus a reward) upon a successful dispute. This function requests a price from the OptimisticOracle. withdrawLiquidation can be called for a liquidation if either:

  1. No dispute has occurred for the liquidation and the liquidationLiveness period has passed.

  2. If a dispute has occurred, and the OptimisticOracle has a price ready in response to the request made when dispute was called.

This function calls _settle (see below) to settle a dispute if there is one. It then rewards the three parties accordingly to the outcome of any dispute. _settle is called in withdrawLiquidation to settle any active dispute for a given liquidation, using the OptimisticOracle’s returned price. If the oracle has no price available, the function reverts. Otherwise, it fetches the price and stores it in liquidation.settlementPrice, calculates requiredCollateral by multiplying the price by the liquidation.tokensOutstanding debt, and checks to see if liquidation.lockedCollateralAfterWithdrawals meets this obligation.

Last updated