Scenarios
- Scenarios
Scenarios
Deploy/Init Pool (WIP)
Pool deployment is triggered by the administrator of the AMM (this person is also the administrator of the router contract - router::admin_address) or by specific roles - pool factory (router::pool_factory_address) and pool admin (router::pool_admin_address). It is done by invoking the operation CREATE_POOL. Pool deployment leads to the processing of the POOL_INIT operation inside the pool contract. This operation is used both - during the initial pool deployment and when the pool administrator wants to change some crucial parameters. Pool deployment consists of two stages
I. Forming and sending state_init data
The state_init code is not the actual pool code, but a basic immutable pool prototype (router::subcodes.pool_prototype_code). The state_init data holds only the fields that define the pool identity:
- Router address
- Jetton0/Jetton1 wallet addresses (these are attached to the router; they are ordered by address hash, so for any pair of jettons there is exactly one possible pool address)
All other storage fields are set to defaults: the pool is marked as not deployed, and the admin and controller addresses are set to BLACK_HOLE_ADDRESS.
Since the pool address is fully determined by the router address and the two jetton wallets, anyone can compute it off-chain, and the same prototype code can be reused for every pool while the actual pool code stays upgradable at deploy time.
II. The state_init message holds as a body the POOL_INIT operation
This message carries everything the prototype needs to become a working pool:
- The actual Pool contract code — the prototype replaces its own code with it via set_code
- Account contract code
- Position NFT contract code
- Pool parameters: tick spacing, initial price, fees, activity flag
- Pool roles: admin, controller, creator (and, when sent by the router admin, also arbiter, ALM and oracle)
Newly created pool starts in a "not deployed" state: the is_deployed flag in state_init is set to false, and the admin address is set to BLACK_HOLE_ADDRESS. While the pool is not deployed, every operation except POOL_INIT is rejected. POOL_INIT itself is only accepted from the router or from the pool admin. Since the admin in state_init is BLACK_HOLE_ADDRESS (an address nobody controls), the only party that can perform the initial deployment is the router. And because the pool address is derived from the state_init that contains the router address, nobody can deploy a pool at the "canonical" address with a different router or a pre-set admin — any tampering with the initial data changes the resulting address. After the initial deployment, POOL_INIT can be repeated to change crucial parameters, but only when it originates from the router admin or the pool admin: an init message proxied by the router on behalf of the pool factory carries a flag that forbids re-initialization of an already deployed pool.
Pool Factory
Pool factory is expected to be a contract callable for anyone. It checks on-chain data validity for pool creation. The pool created by pool factory can only have a predefined number of fee and tick spacing settings
Pool Settings
When creating a pool through the Pool Factory, the settings field selects one of the predefined fee / tick spacing combinations:
| settings | LP fee | Tick spacing | Fee, % |
|---|---|---|---|
| 1 | 5 | 10 | 0.05% |
| 2 | 30 | 60 | 0.3% |
| 3 | 100 | 200 | 1% |
| any other value | 1 | 1 | 0.01% |
LP fee is expressed in units of 1/10000 (0.01%). The protocol fee is fixed by the factory and cannot be chosen. Pools created through the factory are activated immediately. Custom fee and tick spacing values are only available to addresses whitelisted by the factory administrator.
Jetton Requirements
Permissionless pool creation works with any jetton whose minter supports on-chain wallet discovery (TEP-89):
- The minter must handle
provide_wallet_address(op0x2c76b973) and reply withtake_wallet_address(op0xd1735400).
The factory does not trust jetton wallet addresses supplied by the caller. Instead, it deploys a temporary order contract (one per jetton pair) that queries both jetton minters on-chain for the router's wallet addresses. Only after both minters respond does the factory proceed with pool creation. If a minter does not implement TEP-89, the discovery never completes and the pool cannot be created through the permissionless flow.
No other on-chain methods are required from the jetton.
If your jetton doesn't support TEP-89 please contact the team and we will gladly help you with pool creation
Mint
Position minting is done by sending two jettons to the router. Generally, the user calls pool::getMintEstimate to estimate the number of jettons that the person needs to send to mint a particular amount of liquidity in the given price range (tick range). Optionally, the user may send more jettons than needed to account for possible slippage.
While sending both jettons to router wallets, the user sends the payload that contains the position parameters. On receiving the jettons (operation JETTON_TRANSFER_NOTIFICATION ) router would compute the pool address and forward the operation to the pool (POOL_FUND_ACCOUNT)
The pool uses a special structure - user Account (Account) to create a barrier that would collect the proof that two jettons are funded and order to mint liquidity and then send it back to the pool for actual mint execution
Swap
Generally user calls pool::getSwapEstimate to estimate the amount of the jettons that he/she needs to send to swap and then sends jettons to the router with a payload describing the future swap. The router forwards the swap to the pool by dynamically computing the pool address.
Burn and Collect
There are two ways that can trigger the burn.
Getter
Here is an example of the onchain getter, that is obviously async, but can be useful sometimes