Skip to content
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

Merged
merged 4 commits into from
Oct 2, 2021

Conversation

Chris-Hibbert
Copy link
Contributor

@Chris-Hibbert Chris-Hibbert commented Sep 3, 2021

Uses Ratios pervasively in calculating prices and fees
Uses virtual pools to calculate prices and do swaps for two hop (aka "doubleswap") trades

@Chris-Hibbert Chris-Hibbert added enhancement New feature or request Beta Core Economy OBSOLETE in favor of INTER-protocol AMM labels Sep 3, 2021
@Chris-Hibbert Chris-Hibbert added this to the Beta Phase 4: Governance milestone Sep 3, 2021
@Chris-Hibbert Chris-Hibbert self-assigned this Sep 3, 2021
@Chris-Hibbert Chris-Hibbert force-pushed the constantProductAMM branch 2 times, most recently from 2349786 to aeebce0 Compare September 23, 2021 00:53
@dckc dckc self-requested a review September 29, 2021 22:20
Base automatically changed from constant-Product to master September 30, 2021 21:22
Chris-Hibbert added a commit that referenced this pull request Sep 30, 2021
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>
Copy link
Member

@dckc dckc left a 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.

Copy link
Member

@dckc dckc left a 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
Copy link
Member

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.

Copy link
Contributor Author

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
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to ERef<>.

};

/** @type {XYKPool} */
const pool = Far('pool', {
Copy link
Member

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...)

Copy link
Contributor Author

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.

Copy link
Member

@dckc dckc left a 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.

Comment on lines 26 to 27
* @param {bigint} protocolFee
* @param {bigint} poolFee
Copy link
Member

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%?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect there is a AMM design document that I missed where I could confirm that @rowgraus , @btulloh , @dtribble are content that we don't require finer resolution than a basis point for fee ratios. Got a pointer handy?

Copy link
Contributor Author

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.

@dckc dckc force-pushed the constantProductAMM branch from 2d72e7c to 7b769ac Compare October 1, 2021 23:01
Copy link
Member

@dckc dckc left a 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...

Comment on lines +72 to +89
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);
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

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) => {
Copy link
Member

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.

Copy link
Member

@dckc dckc left a 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
@Chris-Hibbert Chris-Hibbert merged commit 3f53592 into master Oct 2, 2021
@Chris-Hibbert Chris-Hibbert deleted the constantProductAMM branch October 2, 2021 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
AMM Core Economy OBSOLETE in favor of INTER-protocol enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants