-
Notifications
You must be signed in to change notification settings - Fork 212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(vault): liquidation penalty handled by liquidation contracts #5343
Conversation
import { AmountMath } from '@agoric/ertp'; | ||
import { Far } from '@endo/marshal'; | ||
|
||
import { makeTracer } from '../makeTracer.js'; | ||
|
||
const trace = makeTracer('LiqMin', false); | ||
|
||
// ??? is this contract used only for tests and demo purposes? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
currently only used that way, but also available to governance to fall back to.
// all the proceeds from AMM sale are on the vault seat instead of a staging seat | ||
// ??? ^ okay? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why drop penaltyPoolSeat
? That seemed like a good place from which to stage funds going to the reserve.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The requirements of the ticket are that the contract manages where funds go.
They each have their own penaltyPoolSeat
now. I still have to wire up moving the assets out to the reserve.
// ??? remove penalty pool from vault factory | ||
// used to be funded from liquidation penalty | ||
t.deepEqual(await E(vaultFactory).getPenaltyAllocation(), {}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's correct to take the penalty funds out of the vault, but then they have to be accessible (even if we aren't yet retrieving them) from the liquidation contracts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but I'm not sure that test-vaultFactory
needs to be concerned with that. It's a concern of the liquidation contracts what they do with the liquidationPenalty
argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see I misread your comment. Agree completely and working on it.
@@ -241,7 +241,8 @@ export const startVaultFactory = async ( | |||
{ | |||
consume: { | |||
chainTimerService, | |||
priceAuthority, | |||
priceAuthority: priceAuthorityP, | |||
reservePublicFacet: reservePublicFacetP, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
odd... usually we don't bother putting public facets in the produce / consume space, since we can get the instances via agoricNames and then the publicFacet via zoe
But if that's outside the scope of this PR...
to permit more stuff to be consumed, add it to https://github.com/Agoric/agoric-sdk/blob/master/packages/run-protocol/src/core-proposal.js#L40-L46
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks! 842b068
const creatorFacet = Far('debtorInvitationCreator', { | ||
makeLiquidateInvitation: () => zcf.makeInvitation(debtorHook, 'Liquidate'), | ||
const creatorFacet = Far('debtorInvitationCreator (minimum)', { | ||
makeLiquidateInvitation: () => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
renamed à la #5179
* @param {Amount<'nat'>} debt - after incurring penalty | ||
* @param {Amount<'nat'>} penaltyPortion | ||
*/ | ||
const partitionProceeds = (proceeds, debt, penaltyPortion) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now that the math is split between two contracts, not worth having this combo fn
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is basically right, but I have a few questions and suggestions.
const debtPaid = debtorSeat.getAmountAllocated('Out', debtBrand); | ||
const penaltyPaid = AmountMath.min(penalty, debtPaid); | ||
|
||
// Allocate penalty portion of proceeds to a seat that will be transferred to reserve |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not the seat that will be transferred...
// Allocate penalty portion of proceeds to a seat that will be transferred to reserve | |
// Allocate penalty portion of proceeds to a seat that will hold it for transfer to reserve |
@@ -276,15 +298,28 @@ const start = async zcf => { | |||
}); | |||
} | |||
} | |||
|
|||
// Now we need to know how much was sold so we can pay off the debt. | |||
// We can use this because only liquidation adds debt brand to the seat. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// We can use this because only liquidation adds debt brand to the seat. | |
// We can use this seat because only liquidation adds debt brand to it |
amountIn, | ||
paid: debtorSeat.getCurrentAllocation(), | ||
amounts, | ||
}); | ||
|
||
// Now we need to know how much was sold so we can pay off the debt. | ||
// We can use this because only liquidation adds debt brand to the seat. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// We can use this because only liquidation adds debt brand to the seat. | |
// We can use this seat because only liquidation adds debt brand to it |
E(liqSeat).getOfferResult(), | ||
]); | ||
// all the proceeds from AMM sale are on the vault seat instead of a staging seat | ||
// ??? ^ okay? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's fine that all the proceeds end up on the VaultSeat. You can drop the ???
comment.
t.deepEqual(await E(vaultFactory).getPenaltyAllocation(), { | ||
RUN: AmountMath.make(runBrand, 30n), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I expected the new PenaltySeats to have accessors like this. Why don't they?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
closes: #5167
Description
Moves the penalty charging concern from Vault Factory contract to the liquidation contracts. It's up to them what to do with the
penaltyRate
input.This also removes the
penaltyPoolSeat
since it's raison d'être n'est plus.Next up is #5367
Security Considerations
Empowers the liquidation contracts to charge or not charge the liquidation penalty specified by
penaltyRate
.Provides them a public facet of the asset reserve.
Documentation Considerations
--
Testing Considerations
Updated test setup to accommodate wiring of the
reserve
instance. The test of liquidation penalty gathering (removed here) will be part of #5367.