04 / BUILD8 MIN READ

Contracts and integration

An integration must identify the chain, pool core, ABI and module revision. A router address copied from an old report can be replaced; a new local ABI may be incompatible with the pool still deployed.

The multiple-wall views below describe the API in preparation. They are not announced as available on historical Sepolia. Export the validated release’s ABI and verify runtimes before connecting a client.

Pool identity

The PoolKey contains currency0, currency1, fee, tickSpacing and hooks. For CUBIT, native ETH is currency0 and the CUBIT token is currency1.

Field Expected value
currency0 Zero address, representing native ETH
currency1 Token of the identified deployment
fee 100 in the targeted new version; 3000 on historical Sepolia
tickSpacing 10 in the sources reviewed
hooks Hook of the identified deployment

The poolId depends on this entire key. Changing only fee in a frontend does not turn an old pool into a new deployment.

Resolving modules at the same block

First read the registry anchored in hook.v2(). Then resolve available module addresses and moduleRevision at the same block. Check their connections to the core.

Here is a read-only fragment to use with an already configured viem client and a verified registry address:

import { parseAbi, type Address, type PublicClient } from "viem";

const registryAbi = parseAbi([
  "function router() view returns (address)",
  "function moduleRevision() view returns (uint256)",
]);

export async function readRelease(
  client: PublicClient,
  registry: Address,
) {
  const blockNumber = await client.getBlockNumber();
  const [router, revision] = await Promise.all([
    client.readContract({ address: registry, abi: registryAbi,
      functionName: "router", blockNumber }),
    client.readContract({ address: registry, abi: registryAbi,
      functionName: "moduleRevision", blockNumber }),
  ]);
  return { blockNumber, router, revision };
}

This fragment alone does not verify all connections and authorizes no signing. The repository frontend checks them in resolveRelease, readRelease and assertCurrentDeployment.

Before each signature, compare the modules and revision with the context already reviewed by the user. Do not silently redirect an approval.

Reading multiple walls

Planned hook view Result / use
wallCount() Number of historical identifiers, separate from the active position count
activeWallCount() Number of active walls in the state read
activeWallId(index) Permanent ID at an index in the current active list
latestWallId() ID of the last funded wall; first check that a wall exists
walls(id) (int24 lower, uint128 liquidity, uint256 idleEth, uint256 fundedEth)
wallIdleEth() Total ETH remainders allocated to walls

Active list indexes can change after absorption. Keep the wall’s ID as its identity, not its traversal index. Read the count and elements at the same block.

fundedEth represents cumulative new funds actually placed at that tick. It must not be displayed as remaining depth. idleEth represents a remainder attached to the wall, separate from its deployed liquidity.

A range’s upper bound is lower + tickSpacing. Present assets are calculated using geometry and the current price, or through Lens views adapted to this version. New fees still free for placement remain separate in pendingFloorEth.

The historical fields floorPrice and netFloorPrice no longer summarize all levels. The last funded wall’s reference can fall when the current target falls; ticks of walls already created remain fixed.

Units and orientation

CUBIT and ETH amounts use 18 decimals. Lens-derived prices are expressed in ETH per CUBIT at 1e18 scale. The v4 tick follows CUBIT-per-ETH orientation; it decreases when the ETH-per-CUBIT price increases.

Use bigint integers for amounts and calculations before formatting. Converting to Number too early can lose precision. The “7k” base is interpreted as USD 7 000 FDV on 21 million CUBIT: its ETH conversion must be recorded before deployment, then the initial price remains fixed. Do not mix USD, wei and token units.

Router methods

swapExactIn(
    PoolKey key, bool zeroForOne,
    uint256 amountIn, uint256 amountOutMin,
    address recipient, uint256 deadline
)

swapExactOut(
    PoolKey key, bool zeroForOne,
    uint256 amountOut, uint256 amountInMax,
    address recipient, uint256 deadline
)

zeroForOne = true buys CUBIT with ETH. For exact-input, supply amountIn as value; for an exact-output purchase, supply amountInMax, with a surplus refund. A sale uses zeroForOne = false, zero value and CUBIT approval for the router.

Returned amounts follow the router’s net/gross boundaries: net output for exact-input, gross input for exact-output. The contract checks incomplete fills. The quote must be simulated with the correct pool key and version.

Events and errors

Historical events include BuyTaxed, SellTaxed, FloorRaised, SweepExecuted, TokensBurned and BountyPaid. ModuleUpdated tracks module replacements; ReferralBound describes a referral link.

The new library adds WallFunded and WallAbsorbed with the relevant ID. Logs from a library executing in the hook’s context must be indexed at the hook’s emitting address and with the corresponding ABI signatures.

FloorRaised retains a historical name; the name alone is insufficient to conclude that all levels rise. A relay must interpret the identified wall’s funding and the release policy.

In the router, handle in particular Expired, WrongPool, TooLittleReceived, TooMuchRequested, InsufficientOutput and IncompleteInput. For maintenance, eligibility errors and RPC errors are separate. Review the codes and ABI again after multiple-wall validation.

Sources: interfaces/ICubitHook.sol, interfaces/ICubitLens.sol, WallLib.sol, CubitRouter.sol and dapp/src/chain. Wall API documented during implementation on September 10, 2026.

CUBIT / September 10, 2026 Sources and method