-
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
A constant product AMM that charges pool and protocol fees #3791
Conversation
fd77182
to
1e903b9
Compare
51d0f43
to
57e8f50
Compare
2349786
to
aeebce0
Compare
d3dd05c
to
cf3f73a
Compare
aeebce0
to
4584a65
Compare
Constant Product calculations for an AMM. (ref: #3791) type declarations Allow swapOut() to have an empty amountIn representing "no restriction" Drop enforcement in swapIn/swapOut that the quotes are in the forward direction doublePool will need to call them in the reverse direction extract common code in swapIn & swapOut drop reporting on price improvements reduce duplicated code in swap.js Co-authored-by: Kate Sills <kate@agoric.com>
4584a65
to
7b769ac
Compare
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'm struggling to read the code for getInputPrice
. I'd like to discuss it.
packages/zoe/test/unitTests/contracts/vpool-xyk-amm/test-xyk-amm-swap.js
Show resolved
Hide resolved
packages/zoe/src/contracts/vpool-xyk-amm/multipoolMarketMaker.js
Outdated
Show resolved
Hide resolved
packages/zoe/src/contracts/vpool-xyk-amm/multipoolMarketMaker.js
Outdated
Show resolved
Hide resolved
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'd like to discuss the use of Far
on pools.
// This contract must have a "Central" keyword and issuer in the | ||
// IssuerKeywordRecord. | ||
// poolFee is the portion of the fees that go into the pool (in BP). | ||
// protocolFee is the portion of the fees that are shared with validators |
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.
with validators? is that right? Is that the same as the stability pool? We discussed this but now I don't recall your answer.
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.
Mentioning the validators here is too specific. stability pool is one of the names that has been bandied about without resolution, but I'll use it as an improvement over what I wrote.
* @param {(brand: Brand) => boolean} isSecondary | ||
* @param {(brand: Brand, pool: XYKPool) => void} initPool | ||
* @param {Brand} centralBrand | ||
* @param {Timer} timer |
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.
Requiring a Timer
rather than an ERef<Timer>
is awkward. When working on the governance demo, I discovered it's not just a matter of type declarations. Zoe or something really requires a Timer
in some places. This makes no sense to me, since all calls to it are remote.
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.
changed to ERef<>
.
packages/zoe/src/contracts/vpool-xyk-amm/multipoolMarketMaker.js
Outdated
Show resolved
Hide resolved
}; | ||
|
||
/** @type {XYKPool} */ | ||
const pool = Far('pool', { |
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 Far
declaration suggests this might be exposed to callers from other vats, so I'm checking much more closely for defensive correctness.
Is it actually exposed? If not, why Far
? (perhaps using Far
to be conservative is good... I'm still thinking thru it...)
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.
Not exposed outside the module. I'll drop Far
here and in related places.
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'd like to discuss the case of of a zcfSeat
with a non-fungible Central
allocation in XYKPool.addLiquidity
.
* @param {bigint} protocolFee | ||
* @param {bigint} poolFee |
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 take it we're 99.9999% sure we don't need more resolution than 1 in 10,000 for these fees, but I'd like confirmation. Noone in the next several years will want / need a fee ratio of, say, 0.035%?
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.
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 don't have a link for an AMM design doc.
I'm confident that we don't need finer resolution than a basis point. I don't have 6 nines confidence.
2d72e7c
to
7b769ac
Compare
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.
a couple more notes... finishing some stuff up...
liquidityZcfMint.mintGains({ Liquidity: liquidityAmountOut }, poolSeat); | ||
liqTokenSupply += liquidityValueOut; | ||
|
||
poolSeat.incrementBy( | ||
zcfSeat.decrementBy({ | ||
Central: zcfSeat.getCurrentAllocation().Central, | ||
Secondary: secondaryAmount, | ||
}), | ||
); | ||
|
||
zcfSeat.incrementBy( | ||
poolSeat.decrementBy({ Liquidity: liquidityAmountOut }), | ||
); | ||
zcf.reallocate(poolSeat, zcfSeat); | ||
zcfSeat.exit(); | ||
updateState(pool); |
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 stuff between mintGains
and exit
(or maybe reallocate
) feels like some sort of critical section. @erights were you looking into some idiom for those?
@Chris-Hibbert in this case, if something in this section throws, did rights get minted and lost? Or are we safe? Or are we certain that nothing throws?
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 critical. The only place that users' assets are changed is in the reallocate()
call. If something breaks between mint and reallocate, we've leaked RUN into an internal Pool that will ignore it, but the user is protected by offer safety.
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.
leaking RUN seems pretty bad; I was under the impression we wanted to be able to account for every last jot and tiddle at all times. But I can ask around about that separately.
* @param {Ratio} poolFeeRatio | ||
* @returns {VPool} | ||
*/ | ||
const provideVPool = (brandIn, brandOut, poolFeeRatio) => { |
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.
You suggested I study this code until I see how until you can see how singlePool
and doublePool
polymorphically solve the previously complicated problem. I think I get it now. This seems to be where they meet.
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.
looks good.
I have a couple suggested changes and a few comments to consider, but none of them are critical.
To confirm my understanding of what's stored in some of the variables, I added some type declarations as I reviewed the code. They're available in #3920. Feel free to integrate them or not now; if not, I may submit them later.
Uses Ratios pervasively in calculating prices and fees Uses virtual pools to calculate prices and do swaps for two hop trades
4d836a5
to
3c078fe
Compare
Uses Ratios pervasively in calculating prices and fees
Uses virtual pools to calculate prices and do swaps for two hop (aka "doubleswap") trades