Code Monkey home page Code Monkey logo

trident's Introduction

Trident: SushiSwap Next Generation Exchange

Codechecks

Coverage Status

TRIDENT ๐Ÿ”ฑ is a newly developed AMM and routing system from SushiSwap (Sushi). As a system, Trident is not a fork of any existing AMM, though to start, it incorporates popular AMM concepts into a single, upgradeable framework. The Sushi core team began development with Andre Cronje as Deriswap. This development continued on as Mirin developed by LevX. On May 12th, 2021, Sushi began building Trident in earnest on the Mirin/Deriswap foundation.

Extensibility

Trident is designed as an extensible AMM framework that allows developers to add new pool types that conform to the IPool interface. Before launch, an EIP will be submitted for the IPool interface design to help standardize pool interfaces across Ethereum. As new AMM pool types are designed or experimented with, they can be added to Trident so long as they conform to the interface. In this way Trident will at minimum be a superset of all popular AMM pool designs as well as a future-proof architecture for Sushi to build on.

Launch Pools

Initially, Trident has been developed with four primary pool types for launch:

Constant product pools are the "classic" pools that users will be most familiar with, where trading happens between two assets over the x*y=k constant product formula. In this pool type, liquidity providers own both of the pool's assets in a 50:50 ratio, but the pool also supports a native zap-in feature where liquidity can be added in any ratio of the two tokens. This pool is our most "gas optimized" pool, where swaps are up to 25% cheaper than swaps on the existing Sushi AMM.

Concentrated liquidity pools allow liquidity providers to specify a price range on which to provide liquidity. Providing liquidity on a narrower price range has a multiplying effect on the added liquidity, meaning traders will experience lesser price impacts. This makes the Concentrated Liquidity pool more capital efficient than the classic pool, with the tradeoff being that liquidity providers can suffer greater impermanent loss. Each concentrated liquidity pool supports two assets.

Hybrid pools are designed for swapping like-kind assets. They are an implementation of the stableswap curve which is a hybrid of the x*y=k and x+y=k formulas. The pool works by concentrating liquidity around the price of 1 (e.g., 1 USDC per DAI or 1 renBTC per WBTC). Each hybrid pool supports two assets, with larger baskets supported in upcoming implementations.

Index pools are designed to hold from two to eight tokens, each with a different weight. Trading between two assets of the pool happens over a modified version of the constant product formula used in classic pools. The advantage of these pools is liquidity providers can utilize them to create auto rebalancing indices (e.g., a DeFi blue-chip index) that best match their risk profile.

All of these pools will have configurable fees that allow liquidity providers to strike a balance between offsetting their impermanent loss and having the pool stay market competitive.

As a gas-saving measure, Trident further allows pool deployers to disable TWAP oracles. Architecturally, this makes the most sense for common pairs that already have accurate Chainlink price oracles.

BentoBox Integration

Trident is a native application on the Sushi BentoBox vault platform. BentoBox is part of the broader Sushi infrastructure that allows users to build complex, capital-efficient applications on top. BentoBox works by storing tokens to be utilized in strategies and flash lending. Meanwhile, a virtual "share" balance tracked by BentoBox is used by applications like Trident. The yield from BentoBox strategies and flash lending are returned to users, such as liquidity providers, enabling an optimized AMM experience. Indeed, Trident will be the most capital efficient AMM in existence at launch from this DeFi-optimized design.

For instance, if a user were to place a limit order or provide liquidity for a Trident pool, the underlying tokens would be making additional yield even if no swaps were occurring.

Architecture

  • MasterDeployer is used to add/remove factories for various pool types. Users call MasterDeployer to deploy new pools from whitelisted factories.
  • MasterDeployer also controls the fee percentage that goes to xSUSHI, the barFeeTo address.
  • MasterDeployer has an owner (ops multisig), that'll control these parameters.
  • TridentRouter is the main contract that allows interacting with various pools. It is used to initiate swaps and manage liquidity.
  • TridentRouter is the contract that gets whitelisted in BentoBox as the master app to transfer user tokens in/out of Trident pools and BentoBox.

Tines: Routing Engine

Tines is a new routing engine designed by Sushi for the Trident front end. Tines is an efficient multihop/multiroute swap router. Tines will query Trident pool types and consider factors such as gas costs, price impacts, and graph topology to generate a best price solution.

  • Multihop - Tines can swap between multiple pools to get the best price for users.
  • Multiroute - Tines can distribute a trade horizontally to minimize price impacts (slippage).

Different asset types perform better in different pool types. For instance, like-kind assets such as wBTC and renBTC tend to perform better in hybrid pools. Tines will allow routing more effectively to make multiple pools act as a unified pool resulting in drastically reduced price impacts.

License (GPL3)

At Sushi, we believe deeply in growing the open source ecosystem of DeFi. Our Trident contract set will be GPL3. As a matter of principle, Sushi will continue to release all software that we develop or own under GPL3 or other permissive OSS licenses.

Post Launch Roadmap

  • Franchised pools

    • Following the launch of Trident, Sushi will begin formalizing franchised pools for institutional and other permissioned use cases. Franchised pools are a way to allow users to provide liquidity on decentralized exchanges while meeting their compliance needs. As such, these pools will be differentiated from the main Trident AMM system and will allow whitelisting and similar features for liquidity providers and swappers.
  • Storage Proof TWAP

    • The Trident implementation will also eventually allow for the presentation of a storage proof to give two simultaneous snapshots of a cumulative price. To do this, the user using the TWAP price will present a merkle proof where the block root is less than 256 blocks behind the canonical head. On chain, Trident contracts will validate such storage proof and related values to allow an instant TWAP snapshot. Sushi has repurposed another implementation for [Kashi] and is currently deployed on Polygon. Sushi is currently working on a reduced gas consumption version for deployment on Ethereum mainnet.

trident's People

Contributors

bayological avatar chillichelli avatar clearwood avatar crokau avatar decanus avatar eltociear avatar gasperbr avatar jiro-ono avatar levx-me avatar matthewlilley avatar maxsam4 avatar nori-sec avatar okavango avatar penandlim avatar ro5s avatar sarangparikh22 avatar technicallyty avatar thegreathb avatar wjmelements avatar z0r0z avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

trident's Issues

Failing migration tests make other tests fail due to `ProviderError`

When I try to run trident tests locally, Migration.test.ts always fails. Tests only pass if I explicitly

git clone https://github.com/sushiswap/trident
cd trident/
yarn install
yarn build
yarn test
...

  42 passing (2m)
  2 pending
  38 failing

  1) Migration
       "before all" hook for "Should prepare for migration in chef":
     ProviderError: Must be authenticated!
      at HttpProvider.request (node_modules/hardhat/src/internal/core/providers/http.ts:49:19)
      at getNetworkId (node_modules/hardhat/src/internal/hardhat-network/provider/utils/makeForkClient.ts:109:43)
      at Object.makeForkClient (node_modules/hardhat/src/internal/hardhat-network/provider/utils/makeForkClient.ts:40:27)
      at Function.create (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:153:15)
      at HardhatNetworkProvider._init (node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:234:46)
      at async HardhatNetworkProvider._reset (node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:327:5)
      at async HardhatModule._resetAction (node_modules/hardhat/src/internal/hardhat-network/provider/modules/hardhat.ts:206:5)
      at async HardhatNetworkProvider.request (node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:108:18)
      at async Context.<anonymous> (test/Migration.test.ts:11:5)

...

The weird thing is it's only only the tests in test/Migration.test.ts that fail but once they do, every test after them fails with the same message. For example TridentMath:

TS_NODE_TRANSPILE_ONLY=1 npx hardhat test test/Migration.test.ts test/TridentMath.test.ts
  3) TridentMath
       "before all" hook for "TridentMath.sqrt() returns correct values":
     ProviderError: Must be authenticated!

If your run tests for TridentMath only, they succeed:

TS_NODE_TRANSPILE_ONLY=1 npx hardhat test test/TridentMath.test.ts
  TridentMath
    โœ“ TridentMath.sqrt() returns correct values (196ms)


  1 passing (2s)

Event naming

This is more of a nit pick than anything else, but events should always be named in a way which represents an event, meaing that they should be in past tense.

DeployPool -> DeployedPool/PoolDeployed
TransferOwner -> TransferedOwnership/OwnershipTransfered
TransferOwnerClaim -> ClaimedOwnership/OwnershipClaimed

Identifier uniqueness isn't enforced

Pool implementations require a poolIdentifier to satisfiy IPool.

/// @return A unique identifier for the pool type.
function poolIdentifier() external pure returns (bytes32);

However, uniqueness is not enforced, it probably makes sense to do this.

I did suggest an alternative too which might be worth thinking about, and could be quite useful for consumers, a pool indentifier + version e.g ID: ConstantProductPool, VERSION: 1 etc..., uniqueness of the combination would need to be enforced.

Migrate

There are obvious concerns about the ability to set and execute a migrator on the router, however this gives us a major competitive advantage in combination with the master chef, I think realistically we should include it with the new router to retain this advantage for the future.

ConcentratedLiquidityPool ensureTickSpacing logic issue

when the value of lower is TickMath.MIN_TICK and upper is TickMath.MAX_TICK, I think it should be passed _ensureTickSpacing() method. But current _ensureTickSpacing() block this case.

My Suggestion is below.

Current

function _ensureTickSpacing(int24 lower, int24 upper) internal view {
if (lower % int24(tickSpacing) != 0) revert InvalidTick();
if ((lower / int24(tickSpacing)) % 2 != 0) revert LowerEven();
if (upper % int24(tickSpacing) != 0) revert InvalidTick();
if ((upper / int24(tickSpacing)) % 2 == 0) revert UpperOdd();
}

Suggestion

    function _ensureTickSpacing(int24 lower, int24 upper) internal view {
        if (lower != TickMath.MIN_TICK) {
            if (lower % int24(tickSpacing) != 0) revert InvalidTick();
            if ((lower / int24(tickSpacing)) % 2 != 0) revert LowerEven();
        }

        if (upper != TickMath.MAX_TICK) {
            if (upper % int24(tickSpacing) != 0) revert InvalidTick();
            if ((upper / int24(tickSpacing)) % 2 == 0) revert UpperOdd();
        }
    }

Dependencies are broken without the .lock file

If you try to build the project and run tests without relying on the exact versions listed in yarn.lock, many tests fail. Some of the dependencies listed in package.json must be incorrect or not restricted enough.

test:coverage

git clone https://github.com/sushiswap/trident
cd trident/
rm yarn.lock
yarn install
yarn build
yarn test:coverage
> Istanbul reports written to ./coverage/ and ./coverage.json
Error in plugin solidity-coverage: TSError: โจฏ Unable to compile TypeScript:
test/router/helpers/index.ts:1:30 - error TS2305: Module '"@sushiswap/tines"' has no exported member 'findMultiRoute'.

1 import { RToken, MultiRoute, findMultiRoute } from "@sushiswap/tines";
                               ~~~~~~~~~~~~~~

test

TS_NODE_TRANSPILE_ONLY=1 \
npx hardhat test $(
    find test/ -name "*.test.ts" ! -path "test/Migration.test.ts"
)
...
  27 passing (31s)
  2 pending
  43 failing

  1) MultiPool Routing Tests - Random Topologies & Random Swaps
       Random topology output prediction precision is ok:
     TypeError: (0 , tines_1.findMultiRoute) is not a function
      at Object.createRoute (test/router/helpers/index.ts:40:31)
      at Context.<anonymous> (test/router/RoutingMultiPoolComplex.test.ts:51:34)
      at processTicksAndRejections (internal/process/task_queues.js:97:5)
      at runNextTicks (internal/process/task_queues.js:66:3)
      at listOnTimeout (internal/timers.js:523:9)
      at processTimers (internal/timers.js:497:7)
...
  9) HybridPool Typescript == Solidity check
       Check regular liquidity values
         Test 1:

      swap amount not close enough to predicted amount
      + expected - actual

      -false
      +true
      
      at checkSwap (test/router/RoutingHybrid.test.ts:162:72)
      at processTicksAndRejections (internal/process/task_queues.js:97:5)
      at runNextTicks (internal/process/task_queues.js:66:3)
      at listOnTimeout (internal/timers.js:523:9)
      at processTimers (internal/timers.js:497:7)
      at async Context.<anonymous> (test/router/RoutingHybrid.test.ts:188:11)
...
  40) Concentrated Pool Routing
       swap without crossing:

      AssertionError: expected NaN to be below 1e-12
      + expected - actual

      -NaN
      +1e-12

      at Context.<anonymous> (test/router/RoutingCL.test.ts:71:54)
      at runMicrotasks (<anonymous>)
      at processTicksAndRejections (internal/process/task_queues.js:97:5)
      at runNextTicks (internal/process/task_queues.js:66:3)
      at listOnTimeout (internal/timers.js:523:9)
      at processTimers (internal/timers.js:497:7)

ConcentratedLiqudity additional balance checks

ConcentratedLiquidity pools need additional checks to validate balances

In the existing tests that add liquidity to a CL pool should have and additional requirement to remove all liquidity and then validate the pool balances.

There is an expectation of remaining dust in the pool. The acceptable value is less than a value less that 10 * (10 ** 18) of any given token.

Deterministic exact output functionality is lost

There are two types of Trade which guarentee determisim in their own respects, exact input or exact output.

In my opinion a genius design decision in earlier versions of AMMs, however Trident only supports a deterministic input which is problematic for a number of reasons and common use cases of an AMM.

ExactIn - You have a specific input, the input is determistic, you will never use more input than you expect to recieve some margin (slippage) of output.

This is better understood in my mind as a seller looking to sell a specific amount of tokens, with margin on the output.

ExactOut - You have a specific output, the output is determistic, you will never get more output than you expect in return for some margin (slippage) of input.

This is better understood in my mind as a buyer looking to buy a specific amount of tokens, with margin on the input.

These are two distinct, or rather inverse functions, which have their own use cases. I believe the decision was originally made to include them in earlier versions of AMMs for a good reason, and belive we need to support or else we we lose the ability to cater for the latter case, ExactOut.

Examples:

  • I want 1 PUNK BASIC
  • I want 0.1 SAK3 to qualify for airdrop

You could list a substantial number of common cases like this which require exact out to be both determistic and reliable.

Solutions:

  • Re-architecture of the single router into a generic, if it's desirable to use one router only.
  • Multiple routers

And functionality added to support exactOut for each pool type.

Hacky solutions:

  • Remove ability to select an output amount and only allow input amount. I don't think this is desirable and will frustrate users.
  • Hacks to give appearance of exact out. This will be prone to two, probably common, unexpected results:
    1. Revert
    2. Spending more than you need, and getting more output than you want.

In both cases above this will require a substantially rethink and evaluation of the UI from top to bottom, supporting libraries, and other areas of the application outside of trident too. Timescale for this would be an unknown and substantial, and I believe results would not be great in terms of UX and predictability.

ConcentratedLiquidityPool:rangeFeeGrowth issue

function rangeFeeGrowth(int24 lowerTick, int24 upperTick) public view returns (uint256 feeGrowthInside0, uint256 feeGrowthInside1) {
int24 currentTick = nearestTick;
Tick storage lower = ticks[lowerTick];
Tick storage upper = ticks[upperTick];

When calculating feeGrowth, currentTick must be calculated based on the current price for it to be calculated correctly.

  • AS-IS
int24 currentTick = nearestTick; 
  • TO-BE
int24 currentTick = TickMath.getTickAtSqrtRatio(price);

Hidden dependencies between tests - `Router.test.ts` makes `_ConstantProduct.test.ts` fail if run before

Summary

There seems to be an implicit dependency between test suites because whether they fail or not depends on their order. In particular _ConstantProduct.test.ts fails if you run Router.test.ts before it.

This is especially problematic because to work around #283 I need to exclude some tests. Hardhat does not seem to have a command-line option for that so I'm doing it like this:

tests_to_run=$(find test/ -name "*.test.ts" ! -path "test/migration/Migration.test.ts")
npx hardhat test $tests_to_run

This unfortunately may produce a different order than the one Hardhat uses.

How to reproduce

_ConstantProduct.test.ts and Router.test.ts

This fails:

npx hardhat test test/Router.test.ts test/constant-product/_ConstantProduct.test.ts
  Constant Product Pool Old
    1) "before all" hook in "Constant Product Pool Old"


  9 passing (6s)
  1 failing

  1) Constant Product Pool Old
       "before all" hook in "Constant Product Pool Old":

      AssertionError: expected '0x4B8297ba8ab03Ad9Dc81d09edD9EAB58e7d1100a' to equal '0xAD806Ef1a19DB65F12C08E0f6101Eb4cD5004CCd'
      + expected - actual

      -0x4B8297ba8ab03Ad9Dc81d09edD9EAB58e7d1100a
      +0xAD806Ef1a19DB65F12C08E0f6101Eb4cD5004CCd

      at initialize (test/harness/ConstantProduct.ts:99:25)
      at async Context.<anonymous> (test/constant-product/_ConstantProduct.test.ts:8:5)

Reversing the order fixes the problem:

npx hardhat test test/constant-product/_ConstantProduct.test.ts test/Router.test.ts
  Constant Product Pool Old
    #swap
      โœ“ Should do 24 types of swaps (3300ms)
    #mint
      โœ“ Balanced liquidity to a balanced pool (109ms)
      โœ“ Add liquidity in 16 different ways before swap fees (1938ms)
      โœ“ Add liquidity in 16 different ways after swap fees (1973ms)
    #burn
      โœ“ Remove liquidity in 12 different ways (2649ms)

...

  14 passing (18s)

Sorted paths

If you sort the paths to work around it, it still fails, the errors are just different. The test suite seems to be very brittle with regard to test ordering.

tests_to_run=$(find test/ -name "*.test.ts" ! -path "test/migration/Migration.test.ts" | LC_ALL=C sort)
npx hardhat test $tests_to_run
  113 passing (3m)
  3 pending
  2 failing

  1) Constant Product Pool Old
       #mint
         Add liquidity in 16 different ways before swap fees:

      AssertionError: Expected "49000000000000000000" to be equal 0
      + expected - actual

       {
      -  "_hex": "0x00"
      +  "_hex": "0x02a802f8630a240000"
         "_isBigNumber": true
       }

      at assertArgsArraysEqual (node_modules/@ethereum-waffle/chai/dist/cjs/matchers/emit.js:58:54)
      at tryAssertArgsArraysEqual (node_modules/@ethereum-waffle/chai/dist/cjs/matchers/emit.js:65:20)
      at /tmp/ext-test-Trident-fjO08G/ext/node_modules/@ethereum-waffle/chai/dist/cjs/matchers/emit.js:77:13
      at runMicrotasks (<anonymous>)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)
      at runNextTicks (node:internal/process/task_queues:65:3)
      at listOnTimeout (node:internal/timers:536:9)
      at processTimers (node:internal/timers:510:7)
      at async addLiquidity (test/harness/ConstantProduct.ts:149:3)
      at async addLiquidityInMultipleWays (test/constant-product/_ConstantProduct.test.ts:73:7)

  2) Constant Product Pool Old
       #mint
         Add liquidity in 16 different ways after swap fees:

      AssertionError: Expected "35000000000000000000" to be equal 0
      + expected - actual

       {
      -  "_hex": "0x00"
      +  "_hex": "0x01e5b8fa8fe2ac0000"
         "_isBigNumber": true
       }

      at assertArgsArraysEqual (node_modules/@ethereum-waffle/chai/dist/cjs/matchers/emit.js:58:54)
      at tryAssertArgsArraysEqual (node_modules/@ethereum-waffle/chai/dist/cjs/matchers/emit.js:65:20)
      at /tmp/ext-test-Trident-fjO08G/ext/node_modules/@ethereum-waffle/chai/dist/cjs/matchers/emit.js:77:13
      at runMicrotasks (<anonymous>)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)
      at runNextTicks (node:internal/process/task_queues:65:3)
      at listOnTimeout (node:internal/timers:536:9)
      at processTimers (node:internal/timers:510:7)
      at async addLiquidity (test/harness/ConstantProduct.ts:149:3)
      at async addLiquidityInMultipleWays (test/constant-product/_ConstantProduct.test.ts:73:7)

Visual overview of contracts and their relationships

Thank you for the awesome Sushi team for shipping an excellent product.

As the product is quite complex, does there exist visual documentation regarding the Trident contract set how the different contracts are related and interact? For example, a UML diagram would help external developers to get up to the speed up fast.

Test coverage

We should be aiming for complete code coverage, at least of relevent contracts for intial release.

Master Deployer is already covered.

ConstantProductPoolFactory, ConstrantProductPool & Router need some work to hit 100%.

ConcentratedLiquidityPoolManager Allowance Check Issue

referenced : ConcentratedLiquidityPoolManager.sol

Is there any reason why it is possible to call only msg.sender?

require(msg.sender == ownerOf(tokenId), "NOT_ID_OWNER"); 

If this happens, it will be difficult to create a 3rd party contract for the position NFT in the future. How about changing it to _isApprovedOrOwner as shown below?

require(_isApprovedOrOwner(msg.sender, tokenId), "NOT_ALLOWED");;

RELATED CODES

require(address(position.pool) == address(pool), "POOL_MIS_MATCH");
require(position.lower == lower && position.upper == upper, "RANGE_MIS_MATCH");
require(ownerOf(positionId) == msg.sender, "NOT_ID_OWNER");

function burn(
uint256 tokenId,
uint128 amount,
address recipient,
bool unwrapBento,
uint256 minimumOut0,
uint256 minimumOut1
) external returns (uint256 token0Amount, uint256 token1Amount) {
require(msg.sender == ownerOf(tokenId), "NOT_ID_OWNER");

function collect(
uint256 tokenId,
address recipient,
bool unwrapBento
) public returns (uint256 token0amount, uint256 token1amount) {
require(msg.sender == ownerOf(tokenId), "NOT_ID_OWNER");

IndexPool mint

IndexPool mint function has strange behaviour:

  • It doesn't check pool balance income
  • At first launch It adds 1/100 of 'toMint' value to balanced of all tokens

test:
tests\IndexPool.test.ts'pool balance should be equal to transferred value'

Data fetching via Web3 viability

Gathering data via Web3 is not viable via public metered RPCs across networks at the moment

Suggestions

  • Add poolLength to IPoolFactory
  • Add poolAddresses list to IPoolFactory
  • Add getPool function to IPoolFactory
  • Update concrete factory implementations to satisfy new interface

Subgraph viability

One thing I've run into immediately with the subgraph is unable to distinguish with the NewPoolCreated event what factory this is related to since it contains a pool address only and no context on the factory which created it, nor any data to build this pool without making external calls which should be avoided in the subgraph.

I think we may need to include separate events for each pool type since they can have different initial parameters, like constant product (token0, token1, swapFee), hybrid (token0, token1, swapFee, a), etc... but I'm not entirely sure the best way to proceed here, I would be interested on your thoughts.

Other potentially missing events

  • Hybrid Pool: No swap event
  • Hybrid/ConstantProduct: No sync events

Convert calls to low level calls

This should theoretically be cheaper since low-level calls do not check for extcode. However, gas should be compared before and after on the target Solidity version.

IndexPool: swap failing

Isolated test here: https://github.com/sushiswap/trident/blob/master/test/IndexPool.test.ts

IndexPool is currently failing on swap. The _getAmountOut function is returning an unexpectedly large number that causes an overflow when outRecord.amount is updated.

Also appears to be a logic error in the y value calculation - dividing tokenbalanceIn by itself

    function _getAmountOut(
        uint256 tokenBalanceIn,
        uint256 tokenWeightIn,
        uint256 tokenBalanceOut,
        uint256 tokenWeightOut,
        uint256 tokenAmountIn
    ) internal view returns (uint256 finalAmountOut) {
        uint256 weightRatio = tokenWeightIn / tokenWeightOut;
        uint256 adjustedIn = BASE - swapFee;
        adjustedIn = tokenAmountIn * adjustedIn;
        uint256 y = tokenBalanceIn / tokenBalanceIn + adjustedIn; // tokenBalanceIn/tokenBalancein ?
        uint256 foo = pow(y, weightRatio);
        uint256 bar = BASE - foo;
        finalAmountOut = tokenBalanceOut * bar;
    }

ConcentratedLiquidityPool Missing

Howdy,

The link to ConcentratedLiquidityPool via trident/blob/master/contracts/pool/concentrated/ConcentratedLiquidityPool.sol doesn't seem to lead to a valid file.

Is this code forthcoming?

Index Pool Token <> Token mapping

Problem: The UI needs to find the relevant pool addresses for two tokens.
Solution: When deploying an index pool store the pool address under a pools mapping so that every token combination is covered (n*(n-1)/2) combinations.

for(let i = 0; i < pools.length; i++)
for(let j = i + 1; j < pools.length; j++)
pools[tokens[i]][tokens[j]] = pool

Contracts directory restructure

Move each pool type into its own folder. Something like trident/contracts/{constantProduct/concentratedLiquidity/hybrid...}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.