# Technical AMM Documentation

### Overview

Blackhole is a ve(3,3) DEX built on Avalanche, forking from Thena V2 and incorporating multiple AMM types:

* Basic Pools: Uniswap V2-style constant product pools
* Concentrated Pools: Algebra DEX-based range AMM

Blackhole uses a vote-escrow model with $BLACK and $veBLACK to align liquidity incentives and long-term governance, with auto-voting capabilities.

Brand Assets: <https://docs.blackhole.xyz/brand-assets>

***

### Pool Types

#### Basic Pools

**Basic Volatile Pools**

* AMM Model: Constant product formula x \* y = k
* Use Case: Token pairs with high volatility and uncorrelated prices

**Basic Stable Pools**

* AMM Model: Stable-swap invariant (inspired by Curve)  x³y + y³x ≥ k
* Formula: Custom implementation that flattens the price curve around 1:1 to reduce slippage on similarly priced tokens
* Use Case: Pairs like USDC/USDT, stablecoins, and synthetics

Common Features:

* Fee Structure: Flat LP fee, configurable by pool (e.g., 0.2% default)
* Routing Logic: Integrated with Blackhole router to handle swaps across both pool types

Key Highlights:

* Volatile pools for broader DeFi assets
* Stable pools for low-slippage stablecoin swaps
* Low gas cost and composable architecture
* TWAP oracles and on-chain price feeds

***

#### Concentrated Pools (Algebra Integral’s modular architecture)

* AMM Model: Customizable tick-based range liquidity AMM
* Fee Structure: Static fee model

Key Features:

* Efficient capital use with narrow-range liquidity

***

### AMM Architecture&#x20;

#### Router Layer

* Unified router handles route discovery and execution
* Multi-hop support across Algebra and Uniswap V2 pools
* Implements price impact protection, slippage checks, and gas optimizations

#### Pool Creation

* Creating a new pool requires specific permissions; it is not a permissionless process. If you wish to have a particular pool created, please contact us via discord to initiate the request.

#### Liquidity Positions

Basic Pools

* Staked: Earn protocol emissions, and fees contribute to the pool's gauge.
* Unstaked: Earn the generated fees.

Concentrated Pools

* Staked: Receive protocol emissions for positions within the active liquidity range. Fees contribute to the pool's gauge.
* Unstaked: Receive neither fees nor emissions. Fees contribute to the pool’s gauge.

#### Modularity

* Bridges planned for multichain liquidity sync (e.g., Ethereum, Base)
* Governance contracts modularized for upgrades

***

### ve(3,3) Architecture&#x20;

#### Voting & Incentives

* Uses ve(3,3) mechanism (vote-escrowed $BLACK)
* Weekly epochs where veNFT holders vote on pools to receive emissions
* Epoch flips on Thursday at 00:00 UTC every week
* First Epoch Flip 07/17/2025
* Auto-vote module to maximize voting APR via delegation

#### Emissions

* Emissions to pools are based on vote weights

***

### Technical Details

#### Derive Pool addresses&#x20;

**Basic Pool:**

bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters

pair = address(new Pair{salt: salt}(factory, token0, token1, stable));

**Concentrated Pool:**&#x20;

function computePoolAddress(address token0, address token1) public view override returns (address pool) {

&#x20;   pool = address(uint160(uint256(keccak256(abi.encodePacked(hex'ff', poolDeployer, keccak256(abi.encode(token0, token1)), POOL\_INIT\_CODE\_HASH)))));

&#x20; }

&#x20;bytes32 public constant POOL\_INIT\_CODE\_HASH = 0xeaa3eea3233916c82fe1281a51bd9cde844b7c4673c0714ca0028a57f5634752;

**customPoolDeployer**

<table data-header-hidden><thead><tr><th width="281.06640625"></th><th></th></tr></thead><tbody><tr><td>customPoolDeployer<br>tickSpacing_1</td><td>0xDcFccf2e8c4EfBba9127B80eAc76c5A122125d29</td></tr><tr><td>customPoolDeployer<br>tickSpacing_50</td><td>0x58b05074D52D1a84D8FfDAddA3c1b652e8C56994</td></tr><tr><td>customPoolDeployer<br>tickSpacing_100</td><td>0xf9221dE143A0E57c324bF2a0f281e605e845D767</td></tr><tr><td>customPoolDeployer<br>tickSpacing_200</td><td>0x5D433A94A4a2aA8f9AA34D8D15692Dc2E9960584</td></tr></tbody></table>

### Sampling

**Basic Pool**

* There is a function in PairContract called getAmountOut
* It takes Amount in and token in and returns the price for the second token

**Concentrated Pool**

* Contract: QuoterV2
* Function: quoteExactInputSingle
* Takes below input:

address tokenIn;

address tokenOut;

address deployer;

uint256 amountIn;

uint160 limitSqrtPrice;

* deployer will be different for different tick\_spacing(mentioned above)
* limitSqrtPrice: The price limit of the pool that cannot be exceeded by the swap

#### Settling&#x20;

**Non native tokens**

* Contract: RouterV2
* Function: swapExactTokensForTokens
* Params:

uint amountIn,

uint amountOutMin,

IRouter.route\[] calldata routes,

address to,

uint deadline<br>

* Router:

address pair;

address from;

address to;

bool stable;

bool concentrated;

address receiver;

**Native Tokens**

* Contract: RouterV2
* Function: swapExactETHForTokens
* Params:

uint amountOutMin, IRouter.route\[] calldata routes, address to, uint deadline

* Router

address pair;

address from;

address to;

bool stable;

bool concentrated;

address receiver;

**FOT Tokens**

* Contract: RouterV2
* Function: swapExactTokensForTokensSupportingFeeOnTransferTokens
* Params:

uint amountIn,

uint amountOutMin,

IRouter.route\[] calldata routes,

address to,

uint deadline<br>

* Router

address pair;

address from;

address to;

bool stable;

bool concentrated;

address receiver;<br>

* Gauge addresses for a pool

The GaugeManager contract includes a function called gauges that returns the corresponding gauge address when provided with a pool address.

GaugeManager Address: 0x59aa177312Ff6Bdf39C8Af6F46dAe217bf76CBf6

* Stake NFT for emissions

You can deposit the NFT by calling the deposit function with the tokenid on the gauge contract associated with the respective pool.

### Mainnet Contract Addresses

#### Core Contracts

<table data-header-hidden><thead><tr><th width="301"></th><th></th></tr></thead><tbody><tr><td>Contract Name</td><td>Address</td></tr><tr><td>BLACK</td><td>0xcd94a87696FAC69Edae3a70fE5725307Ae1c43f6</td></tr><tr><td>RouterV2</td><td>0xe946A9f39312E2346BA79DAb865B0e9A74f2F981</td></tr><tr><td>VoterV3</td><td>0xE30D0C8532721551a51a9FeC7FB233759964d9e3</td></tr><tr><td>VotingEscrow</td><td>0xEac562811cc6abDbB2c9EE88719eCA4eE79Ad763</td></tr><tr><td>GaugeManager</td><td>0x59aa177312Ff6Bdf39C8Af6F46dAe217bf76CBf6</td></tr><tr><td>GaugeFactory</td><td>0x9E95eF7D8b87708641923C48C4eB298ED7CA6552</td></tr><tr><td>GaugeFactoryCL</td><td>0x6B6a3D5A1c536aCE1D761685aF241b2cb7a6eA5E</td></tr><tr><td>GaugeOwner</td><td>0xDD35894a790ee9625c3aAD49E8bd14e135F3F946</td></tr><tr><td>PairFactory</td><td>0xfE926062Fb99CA5653080d6C14fE945Ad68c265C</td></tr><tr><td>PairGenerator</td><td>0x34098b39Ec2E2C1A8F815bb8fA840D0D389afE1c</td></tr><tr><td>BlackClaim</td><td>0x91B8C8c51A11a7033C34257C3768035EfF4F7736</td></tr><tr><td>AutoVotingEscrowManager</td><td>0x3755DF8a937e9505aF7B14D8b13E83f133Ed11c3</td></tr><tr><td>SetterTopNPoolsStrategy</td><td>0x5B0f5Acde0a779856D6885A67253529C235929e6</td></tr><tr><td>setterVoteWeightStrategy</td><td>0x4cD13301C1B0555272Be010BfBE8901a55E520f2</td></tr><tr><td>GenesisPoolManager</td><td>0x0EB1e103116b8Ec5f13a72F6943440340c4840dd</td></tr><tr><td>GenesisPoolFactory</td><td>0xdeB50ac7A0a03332626B3c45EB20e7310653260F</td></tr><tr><td>AuctionFactory</td><td>0x553901e346fCaDeBFd15ADffd2bA3c58AC6F9988</td></tr><tr><td>FixedAuction</td><td>0x9d45E1acf9F164be11eeaE206B459DD575EE0bB0</td></tr><tr><td>BribeFactory</td><td>0xfE842861b9F79Bb77CCb6043731D433D63B365dF</td></tr><tr><td>GenesisPoolApi</td><td>0x8ba179fbbc41d36573097a6cc9924DB7c3978fdC</td></tr><tr><td>MinterUpgrdeable</td><td>0xAcc34Ad51457930989fB5050C2Dce6339F06479B</td></tr><tr><td>PermissionRegistry</td><td>0x751B7152AA11E39216cd00c0F65311Efdf1A65ff</td></tr><tr><td>RewardDistributor</td><td>0x7c7BD86BaF240dB3DbCc3f7a22B35c5bAa83bA28</td></tr><tr><td>TokenApi</td><td>0x58318fD6aDb8cAea00727eE4F579d48e6c9631d1</td></tr><tr><td>TokenHandler</td><td>0xD6b6618cbddfc8F33cC6Ad44FB6557fa900049B7</td></tr><tr><td>VeArtProxy</td><td>0xcA756Ef397b8F039d04b4ff967F43417B723aFdE</td></tr><tr><td>VeNFTApi</td><td>0xb3629c89ed9cB172A3FBa66dfdF8C06A85B35dE9</td></tr><tr><td>VotingBalanceLogic</td><td>0x6CaB6577257523e1D609dE76104764F042F993d2</td></tr><tr><td>VoterFactory</td><td>0x109309E885Ee9023bD22E4f45a347640bb2a82Aa</td></tr><tr><td>RouterHelper</td><td>0x1112F67a7098d80c35fCD139FA951496749dFEC3</td></tr><tr><td>BlackholePairApiV2</td><td>0xFf39C52b6649aF0f73c8D3088344436a5E3B2fB6</td></tr><tr><td>PairBootStrapper</td><td>0xA053Ca9c51524D67e5E435C62031AD2031e09a22</td></tr><tr><td>VotingEscrowSplitHelper</td><td>0xA053Ca9c51524D67e5E435C62031AD2031e09a22</td></tr><tr><td>veNFTAPI</td><td>0xb3629c89ed9cB172A3FBa66dfdF8C06A85B35dE9</td></tr><tr><td>bridgefeewrapper</td><td>0x8C2207C82B54d37b0D3cEB80A50A3392AeB8888B</td></tr><tr><td>clrebalancer</td><td>0x0541B43200ce35D78B97e3aB5351C054289BBE27</td></tr><tr><td>routerhelperzap</td><td>0xE168Fcd8f27c22E1C5E9C7Aa6Cf78aFED82F06C6</td></tr><tr><td>routerhelper</td><td>0x53D569BC4B37ADbBDB6ab447D92ADf42514AE480</td></tr><tr><td>routerhelperimpl</td><td>0xb888979122365ceE81d274e4bb6C970CE42af336</td></tr><tr><td>routerhelperproxyadmin</td><td>0x42A53F5460F126CCcaF57D1b79155c65d229F82B</td></tr><tr><td><br></td><td><br></td></tr></tbody></table>

<br>

#### Algebra Contract

<br>

<table data-header-hidden><thead><tr><th width="302.640625"></th><th></th></tr></thead><tbody><tr><td>Contracts</td><td>Address</td></tr><tr><td>AlgebraPool</td><td>0xA02Ec3Ba8d17887567672b2CDCAF525534636Ea0</td></tr><tr><td>poolDeployer</td><td>0x9B2441037E286d5Bf9456a3BE7b5273fe28DbA1e</td></tr><tr><td>factory</td><td>0x512eb749541B7cf294be882D636218c84a5e9E5F</td></tr><tr><td>vaultFactory</td><td>0xdC0b5db6f5f957AD0aC5e0Af8A2C084077D079B3</td></tr><tr><td>BasePluginV1Factory</td><td>0x038CBa84D1CDf5B0820fC6a1FAE93f42240268bb</td></tr><tr><td>AlgebraFarmingProxyPluginFactory</td><td>0x27ae8c52A41EC52A4150BA6321007eC41702c0F0</td></tr><tr><td>wrapped</td><td>0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7</td></tr><tr><td>entryPoint</td><td>0x580be59A0461eaE3414352c0AbD88e485a294bFc</td></tr><tr><td>tickLens</td><td>0xE66aAe9CB5aB27eC6662C0EC9B9b28764D4a822E</td></tr><tr><td>quoter</td><td>0x7A88C46740fDFE446DD6Ad97cc0A94716848D214</td></tr><tr><td>quoterV2</td><td>0x3e182bcf14Be6142b9217847ec1112e3c39Eb689</td></tr><tr><td>swapRouter</td><td>0xaBfc48e8BED7b26762745f3139555F320119709d</td></tr><tr><td>nftDescriptor</td><td>0xe98aec7FE3648C104fac23a350926c17951cf0be</td></tr><tr><td>proxy</td><td>0x18Bf868878fc0722A7400dE93DCb791aba7D001f</td></tr><tr><td>admin</td><td>0xAFD356BC0dB2B5A0Dc879a2424eF384c0f266Fe9</td></tr><tr><td>nonfungiblePositionManager</td><td>0x3fED017EC0f5517Cdf2E8a9a4156c64d74252146</td></tr><tr><td>mcall</td><td>0x9dF9457D5C55B4C880Dc86C67AE323B00B5be48E</td></tr><tr><td>eternal</td><td>0x01A8A00A6fC8106B94f84aAbAef689Fd0D77271A</td></tr><tr><td>fc</td><td>0xa47Ad2C95FaE476a73b85A355A5855aDb4b3A449</td></tr><tr><td>customPoolDeployer<br>tickSpacing_1</td><td>0xDcFccf2e8c4EfBba9127B80eAc76c5A122125d29</td></tr><tr><td>customPoolDeployer<br>tickSpacing_50</td><td>0x58b05074D52D1a84D8FfDAddA3c1b652e8C56994</td></tr><tr><td>customPoolDeployer<br>tickSpacing_100</td><td>0xf9221dE143A0E57c324bF2a0f281e605e845D767</td></tr><tr><td>customPoolDeployer<br>tickSpacing_200</td><td>0x5D433A94A4a2aA8f9AA34D8D15692Dc2E9960584</td></tr></tbody></table>

<br>

#### Production Graph API

<https://api.goldsky.com/api/public/project_cm8gyxv0x02qv01uphvy69ey6/subgraphs/poap-subgraph-core/avax-main/gn>&#x20;

***

### Testnet Contract Addresses

#### Core Contract

<table data-header-hidden><thead><tr><th width="287.15234375"></th><th></th></tr></thead><tbody><tr><td>Contract Name</td><td>Address</td></tr><tr><td>blackholePairAPIV2</td><td>0xF2E811481576D525f7E7916029e8741bf2DF9F76</td></tr><tr><td>routerHelper</td><td>0xb71f886441789eAb6BDCE9574C77B21563C86DC8</td></tr><tr><td>algebraPoolAPIStorage</td><td>0xf741Dc56cd29Bd808F5596d10861728cf25b1236</td></tr><tr><td>autoVotingEscrowManager</td><td>0xb8124eA2dc3969ad7105658187DC30cb2d20c485</td></tr><tr><td>votingEscrow</td><td>0x4854B431d864A7A9bEeD0033A1ec26c3Dc792F06</td></tr><tr><td>setterVoteWeightStrategy</td><td>0x56c56173943EF5bd1D8246A5263A9C3BD4465121</td></tr><tr><td>pairFactory</td><td>0x61bc896fDddF9822a8683e0c90b325De767b853D</td></tr><tr><td>minterUpgradeable</td><td>0xf08A6071Db572A60471658c627C331b5e49fdd62</td></tr><tr><td>genesisPoolFactory</td><td>0x5871990026C1252970cf15A9ae835a856cC86C6A</td></tr><tr><td>black</td><td>0xa981371A120b0e1BBDcD0abaB1ed509c1084fe5F</td></tr><tr><td>votingBalancingLogic</td><td>0x85CeCD63282dab6Db9e3efDAb7927374C79F6209</td></tr><tr><td>gaugeFactory</td><td>0x7Bd71E0Eb9bebdC0370ed5d467d7889486F3Ee74</td></tr><tr><td>fixedAuction</td><td>0x9eB9e1183e54F87e3Bb68f51A98e3E6fe9695b87</td></tr><tr><td>epochController</td><td>0x6C1cfbeF04695B6b7060C9FaA46ae285AD0d1bBc</td></tr><tr><td>auctionFactory</td><td>0x9aA1cc3d50090d84004a9Dc1936c645580d3Df04</td></tr><tr><td>algebraPoolAPI</td><td>0x515FeBb88788Cb87927BecedaEA9081dEDC22a57</td></tr><tr><td>setterTopNPoolsStrategy</td><td>0x5Add3E69e26742537f5c94b1e7bFECB6F1D28c10</td></tr><tr><td>routerV2</td><td>0x1B6814F3227a246F62bC47b148b3d288Dbc85715</td></tr><tr><td>veArtProxyUpgradeable</td><td>0x0E96f40160FaC2F913C7E271532AF9FBb7C4DE8D</td></tr><tr><td>voterV3</td><td>0xf5b3c13d2CAB18f5E928c2631BD4ef37c26b445D</td></tr><tr><td>genesisPoolAPI</td><td>0x459753FB4E87318Ac889D4AefbF7D348776D1B4B</td></tr><tr><td>votingBalanceLogic</td><td>0x0bb50f3DD11Ab76FB0f3cD0b0E191B775Ca4a493</td></tr><tr><td>genesisPoolManager</td><td>0x6FE1B637fE761aA37C42a72930576bae5c0b3E6B</td></tr><tr><td>tokenHandler</td><td>0x1a0D35a3435dE64c99D1C7C21E873600Cb2748D9</td></tr><tr><td>gaugeFactoryCL</td><td>0xa36BEBffc32aa95b00e648A1d5070dCc0a38F56A</td></tr><tr><td>veNFTAPI</td><td>0xe6cf5e0d066ff0bE8F829f0a926BAc61dcc480F2</td></tr><tr><td>rewardsDistributor</td><td>0xd40C4c763e66782878e1b215f233464Ab6A11327</td></tr><tr><td>permissionsRegistry</td><td>0x845aCc1429B4ac566D285D0d0A0950bb8e4249Bb</td></tr><tr><td>gaugeManager</td><td>0x1e34fc4F04bE8D5878b2fe91C55532c8b70623ec</td></tr><tr><td>wAVAX</td><td>0xb3B3CbEd8243682845C2ff23Ea1FD48e6144E34F</td></tr><tr><td>blackClaims</td><td>0xE196b6ea5d8b295aE2473a4dd7DC16BC0b577fb6</td></tr><tr><td>pairGenerator</td><td>0x4d5a04826845FfeB8Cbe9c72C6b376cCFDf1D47B</td></tr><tr><td>bribeFactoryV3</td><td>0x3f398214d02578beE4DB858827B66CBCd7B8274B</td></tr><tr><td>avm</td><td>0x9809f2b120Ab3633C27C53353E8f299a5b27AB51</td></tr><tr><td>voterFactoryLib</td><td>0x5abF38c8D7dB7436de9D03bDF90A45249b95916A</td></tr><tr><td>tokenAPI</td><td>0x8462941A7E2A1770F13627b8E4eadc35452d50C0</td></tr><tr><td>blackGovernor</td><td>0x879CB8bf552eE95E2225806EA03C8D98c60426ED</td></tr></tbody></table>

#### Algebra Contracts

<table data-header-hidden><thead><tr><th width="304.12109375"></th><th></th></tr></thead><tbody><tr><td>Component</td><td>Address</td></tr><tr><td>poolDeployer</td><td>0xd9708e4870Ce20EF85120855b93A01fC8788878C</td></tr><tr><td>factory</td><td>0xDC41bA754Fd6E524dD7B195B557434760F4952a7</td></tr><tr><td>vaultFactory</td><td>0x76f65Faa67346B9B3CE85fC219768e13564b76c2</td></tr><tr><td>BasePluginV1Factory</td><td>0x2b40319599249B6890E425FbB0d71900Ce81883A</td></tr><tr><td>wrapped</td><td>0xb3B3CbEd8243682845C2ff23Ea1FD48e6144E34F</td></tr><tr><td>entryPoint</td><td>0x0aD81A4D8A4dAA069Ed28e5417ACC1d052F11d0a</td></tr><tr><td>tickLens</td><td>0xBf404A0489994D01c7F5981f9CFDA77862BDF712</td></tr><tr><td>quoter</td><td>0x69318533C3b3Db701663EcC90Dc0E586E28fc594</td></tr><tr><td>quoterV2</td><td>0x74Ff66609d9b2237A86241B2CF453fE4D5728F11</td></tr><tr><td>swapRouter</td><td>0xfcB1d07D8E0BfcccD6Ad7cD74F384f72f0BB2ada</td></tr><tr><td>nftDescriptor</td><td>0x7724b07226D2Be3E6861BbCee045683036bAeE63</td></tr><tr><td>proxy</td><td>0xB4236F81D099a80b55Cd0d748a1b507a4Ed68605</td></tr><tr><td>admin</td><td>0x1ca7502b80a6663e35ec5C5a86a068Fc34115D32</td></tr><tr><td>nonfungiblePositionManager</td><td>0xf7e9491B88FF32C1f8C00c18392b13157DF2B4b9</td></tr><tr><td>mcall</td><td>0xB4eE4e1dD46144355724a9741577027d647a0fB7</td></tr><tr><td>eternal</td><td>0x45e56eB20Cb58DCCB74056867daDb9ACa65E4463</td></tr><tr><td>fc</td><td>0xBadE44EAFCa469c868A0b67f5e540b2b8BE50738</td></tr><tr><td>AlgebraBasePluginV1</td><td>0xf0CE7495c9f3C50CD79Bc6ad3151542bcA9D2Df5</td></tr><tr><td>AlgebraFarmingProxyPluginFactory</td><td>0x9763d20CEeF26B7db6C48E3b5A4B00f948C59600</td></tr></tbody></table>

<br>
