Several execution paths. One wallet boundary.
The frontend reads several providers, but every state-changing action resolves to a concrete router, position manager, pair, or staking contract before the wallet signs.
System map
Connected wallet
├─ Swap ──────── quote engine ─┬─ BitBlocks Router ──────── V2 pair(s)
│ ├─ V3 SwapRouter ─────────── V3 pool(s)
│ ├─ BitBlocks Smart Router ── V2 pair + V3 pool
│ ├─ PancakeSwap Smart Router ─ PancakeSwap V2/V3
│ └─ 1inch router
├─ Liquidity V3 ─ NonfungiblePositionManager ── V3 pool ── position NFT
├─ Liquidity V2 ─ BitBlocks Router ── Factory ── pair / LP token
├─ Earn ───────── MasterChef (many pools) or SmartChef (one pool)
└─ Read-only ──── RPC + app API routes + info backend ── metrics / pools / chartsBitBlocks V2 AMM
Router
The router is an immutable pair of factory and WETH addresses. It exposes standard V2 functions for exact-input and exact-output swaps, adding and removing liquidity, native BNB variants, permit-based removal, and fee-on-transfer supporting swap variants.
For every deadline-protected call, the ensure modifier rejects an expired timestamp. Slippage is enforced by amountOutMin, amountInMax, amountAMin, or amountBMin supplied by the caller.
Factory
The factory stores both token orders in getPair, appends each new pair to allPairs, and deploys deterministic pairs with CREATE2. Only the configured feeToSetter can change feeTo or transfer that setter role.
Pair invariant
amountInWithFee = amountIn × 9975
amountOut = amountInWithFee × reserveOut
/ (reserveIn × 10000 + amountInWithFee)The pair’s swap check subtracts 25 basis points from each input balance before checking x × y ≥ k. That is the source-backed reason the frontend labels BitBlocks V2 hops with a 0.25% LP fee.
Protocol fee
When feeTo is non-zero, _mintFee mints protocol LP tokens during mint or burn from growth in sqrt(k):
liquidity = totalSupply × (rootK − rootKLast) × 8
/ (rootK × 17 + rootKLast × 8)That is 8/25 of fee growth, or about 0.08 of the 0.25 percentage points. feeTo is currently set on the live factory, so the protocol fee is active and liquidity providers keep about 0.17% per trade.
BitBlocks V3 AMM
BitBlocks V3 is a fork of PancakeSwap V3 (v3-core and v3-periphery), which is itself a fork of Uniswap V3. The pool math is unchanged; the differences are names, callbacks (bitblocksV3SwapCallback), fee tiers, the default protocol fee, and governance.
Pools and fee tiers
| Fee | Tick spacing |
|---|---|
0.01% (100) | 1 |
0.05% (500) | 10 |
0.3% (3000) | 60 |
1% (10000) | 200 |
Pools are deployed by BitBlocksV3PoolDeployer with CREATE2; the factory only registers them. A pool address is derived from the deployer, the sorted token pair, the fee, and the pool init code hash.
Each pool tracks sqrtPriceX96, the current tick, active liquidity, and global fee growth. Liquidity is added per tick range, and swaps cross initialized ticks as the price moves. Only liquidity whose range contains the current price earns fees.
Protocol fee
New pools start with feeProtocol = 500 for each direction, meaning 5% of the swap fee goes to the protocol and 95% to in-range liquidity providers. The factory owner can set a pool between 0% and 40% with setFeeProtocol and withdraw accrued protocol fees with collectProtocol.
Position manager
NonfungiblePositionManager mints an ERC-721 for each position (BitBlocks Finance V3 Positions NFT-V1, BBKFI-V3-POS) and stores its pool key, tick range, liquidity, and owed fees. The interface sends every action as one multicall:
| Action | Calls |
|---|---|
| Create position | createAndInitializePoolIfNecessary (new pool only) → mint → refundETH when paying in BNB |
| Increase | increaseLiquidity → refundETH when paying in BNB |
| Remove | decreaseLiquidity → collect → unwrapWETH9 / sweepToken when receiving BNB |
| Collect | collect, optionally with unwrapWETH9 / sweepToken |
increaseLiquidity, decreaseLiquidity and collect check deadline, amount0Min and amount1Min where applicable. decreaseLiquidity, collect and burn require the caller to be the NFT owner or approved.
Routers
SwapRouter
Uniswap-V3-style router for exactInput and exactInputSingle over BitBlocks V3 pools. The deadline lives inside each params struct.
BitBlocks Smart Router
Fork of the PancakeSwap Smart Router with BitBlocks V2 and V3 init code hashes, no StableSwap, and no owner. The interface uses it for two-hop routes that combine a BitBlocks V2 pair and a V3 pool.
Swap quote architecture
V2
The frontend generates direct and base-token candidate paths, batches getAmountsOut across the BitBlocks and PancakeSwap V2 routers, and keeps the best output per router. It reads pair reserves to derive a mid-price and price impact. PancakeSwap V2 is quoted on its classic router but executed through the PancakeSwap Smart Router so the platform fee can be taken on-chain.
All successful quotes are reduced by the platform fee where it applies, adjusted for estimated gas when BNB is on one side, and ranked by the resulting output.
Platform fee on third-party routes
PancakeSwap routes are built as multicall(deadline, [swap to the router, sweepTokenWithFee | unwrapWETH9WithFee]), so the router holds the output for an instant and pays the user minus 0.15% in the same transaction. Because the Smart Router checks amountMinimum before taking its fee, the interface grosses up the user’s minimum received before sending it. 1inch receives the same fee as its fee and referrer parameters. BitBlocks routes never take this fee.
MasterChef
MasterChef stores an array of pool records and one user record per pool and address.
poolReward = blocks × bbkfiPerBlock × allocPoint / totalAllocPoint
pending = user.amount × accBBKFIPerShare / 1e12 − rewardDebtDuring updatePool, the contract mints the calculated pool reward to itself and an additional poolReward / 10 to the developer address. A pool with zero stake skips minting. A deposit first settles pending rewards, transfers the deposit token, applies any depositFeeBP, then updates reward debt. Withdraw follows the same accounting before returning principal.
Owner controls
add, set, and updateEmissionRate are onlyOwner. Pool weight and deposit fee can therefore change. The owner is currently an externally owned account, not a timelock.
Role controls
The current developer address can rotate itself, and the current fee address can rotate itself.
Emergency exit
emergencyWithdraw returns deposited tokens, resets amount and reward debt, and does not pay pending rewards.
Mint dependency
Pool updates require MasterChef to retain authority to call BBKFI mint. BBKFI’s owner is the MasterChef.
SmartChef
Each SmartChef is initialized once by its factory with stake token, reward token, rate, block window, optional user limit, and admin. Rewards are accumulated with a precision factor derived from reward-token decimals.
depositandwithdrawsettle pending rewards before updating debt.stopRewardcan move the end block to the current block.updateRewardPerBlockand schedule updates are allowed only before a pool starts.recoverWrongTokensrejects both the configured stake and reward token.emergencyRewardWithdrawlets the owner withdraw reward tokens.
SmartChef rewards are pre-funded and the owner can stop or withdraw rewards. Treat the displayed end time and APR as current observations, not immutable promises.
Governance and admin roles
| Contract | Controlled by | Privileged actions |
|---|---|---|
| BitBlocks V3 Factory | TimelockController (48h delay) ← Safe multisig | setFeeProtocol, collectProtocol, enableFeeAmount, setLmPoolDeployer, setOwner, and related settings |
| ProxyAdmin (NFT descriptor) | TimelockController ← Safe multisig | Upgrade the position NFT metadata implementation |
| BitBlocks Smart Router | Nobody | No owner functions |
| V3 SwapRouter, QuoterV2, TickLens | Nobody | No owner functions |
| BitBlocks V2 Factory | feeToSetter address | setFeeTo, setFeeToSetter |
| MasterChef | Owner EOA | add, set, updateEmissionRate |
| SmartChef | Each pool’s owner | Stop rewards, withdraw rewards, recover unrelated tokens |
The Safe is the timelock’s only proposer and executor, and the deployer renounced the timelock admin role. Any V3 factory change is therefore scheduled publicly on-chain at least 48 hours before it can execute.
Upgradeability and code changes
The BitBlocks V2 Router, Factory/Pair, MasterChef, BBKFI, SmartChef, V3 pools, V3 factory, position manager, and routers do not use proxy delegation or expose an upgrade function. Changing their logic requires a new deployment.
The one exception is the NonfungibleTokenPositionDescriptor, which builds the NFT’s tokenURI. It sits behind a transparent upgradeable proxy administered by the timelock-owned ProxyAdmin. Upgrading it can change how positions are described, not pool balances or position ownership.
Non-upgradeable code can still contain mutable parameters and admin roles, as listed above.
Failure boundaries
- RPC failures can prevent quotes or pool reads without changing contract state.
- Pool lists, APR and charts depend on the info backend; if it is unavailable, those views degrade while on-chain actions still work.
- A provider returning no route is not equivalent to a protocol-wide liquidity failure.
- A token that violates common ERC-20 expectations can break approval, transfer, reserve, or quote assumptions.
- Slippage and deadline checks deliberately revert when state changes beyond the user’s limits.
- External routes inherit the contract and provider risks of PancakeSwap or 1inch in addition to frontend risk.