Developers

Developer Overview

View as Markdown

Giwater is a deployment of the PancakeSwap Infinity contracts — concentrated-liquidity (CL) pools, a singleton Vault with flash accounting, hooks, UniversalRouter and Permit2 — on GIWA Sepolia. The contracts are the upstream releases compiled without local patches, so Infinity's interfaces, action encodings and SDK conventions apply unchanged.

These pages are for developers building a frontend, bot or indexer against the deployment. Contracts lists every address and ABI; Integration walks through quoting, swapping and providing liquidity.

Network

Network
GIWA Sepolia (testnet)

Chain ID
91342
RPC
https://sepolia-rpc.giwa.io
Explorer
sepolia-explorer.giwa.io
Currency
ETH (Sepolia Ether)

The deployment lives on testnet only. It runs CL pools and nothing else: the router supports Infinity CL swaps, and there are no bin or stable-swap pools. The seeded pools pair each test token with USDC at fixed fee tiers, and none of them has a hook (hooks is the zero address in each pool key). Anyone can create further pools through CLPositionManager.

The explorer runs Blockscout, which also serves an Etherscan-compatible API.

Test Tokens

You need two things: GIWA Sepolia ETH for gas, and the test tokens the pools trade.

  • ETH — from the Nodit Faucet or the GIWA Official Faucet.
  • Test tokens — from the Faucet page. One claim sends a fixed amount of each token, plus ethAmount() of ETH (which can be zero), to the signed-in wallet.

The bundle is BTC (8 decimals), USDC (6), and AAPL, SPCX and SKHY (18 each).

The faucet contract (faucet in the deployment manifest) is not open to arbitrary callers. Its claim(bytes32 eligibilityId, uint256 deadline, bytes signature) requires an authorization signed by the faucet's claim signer, which Giwater issues only after the account links X, and the app's relayer submits the claim and pays its gas. To fund a bot, sign in on the Faucet page with the bot's wallet. The contract's read functions are public: tokens(i) and amounts(i) for the bundle (i from 0 to 4), ethAmount(), COOLDOWN() (currently 24 hours) and nextClaimAt(eligibilityId).

Architecture

How the Giwater contracts call each otherYour app / botviem, ethers, a contractPermit2token approvalspermitexecutemodifyLiquiditiesUniversalRouterswapsCLPositionManagerliquiditylock → lockAcquiredsync / settle / takeswap / modifyLiquidityVaultbalances, flash accountingCLPoolManagerpools, ticks, swap mathaccountAppBalanceDeltahooks, per poolHookscustom pool logicreadCLQuoterquotes (read)CLTickLenstick data (read)
An app or bot calls UniversalRouter to swap and CLPositionManager to manage liquidity, after approving tokens through Permit2. Both open a lock on the Vault, which holds every balance and settles the net amounts at the end through flash accounting; inside that lock they call CLPoolManager, which owns pool state and ticks, records each balance change with the Vault, and invokes a pool's hooks when it has them. CLQuoter and CLTickLens read pool state for quotes and tick data without changing it.

State

  • Vault — the only contract that holds pool tokens. It tracks a delta per locker and currency for the current lock, and per-app reserves.
  • CLPoolManager — every CL pool's slot0 (sqrtPriceX96, tick, fees), tick bitmap, liquidity and positions, keyed by PoolId = keccak256(abi.encode(PoolKey)). Pools are storage entries, not contracts. It reports each operation's balance change to the Vault (accountAppBalanceDelta).
  • Hooks — optional per pool, named in PoolKey.hooks; the enabled callbacks are encoded in PoolKey.parameters. All seeded pools use the zero address.

Lock and Settle

Every state change runs inside one Vault lock:

caller ──▶ UniversalRouter.execute / CLPositionManager.modifyLiquidities
             └─▶ Vault.lock(data)
                   └─▶ caller.lockAcquired(data)
                         ├─ CLPoolManager.swap / modifyLiquidity / donate   → delta(currency) ± amount
                         ├─ Vault.sync(currency) + token transfer + Vault.settle()   → pay a negative delta
                         └─ Vault.take(currency, to, amount)                → receive a positive delta
             lock returns only if every delta is zero; otherwise the transaction reverts

Consequences for integrators:

  • A multi-hop swap transfers only the first input and the final output; intermediate currencies net to zero inside the Vault.
  • Slippage is enforced inside the plan (amountOutMinimum / amountInMaximum) and by the execute deadline, not after settlement.
  • Contracts that call the Vault directly must implement lockAcquired and close every delta themselves.

Entry Points

  • Swaps — UniversalRouter.execute(commands, inputs, deadline) with the INFI_SWAP command and a CL swap action plan ending in settle/take actions. Spends tokens through Permit2.
  • Liquidity — CLPositionManager.modifyLiquidities(payload, deadline); positions are ERC-721 tokens. Mint, increase, decrease and burn are actions in one plan.
  • Approvals — ERC-20 approve(Permit2, …) once, then a Permit2 allowance per spender, from Permit2.approve or a signed permit (PERMIT2_PERMIT command, permitBatch on the position manager).
  • Quotes — CLQuoter.quoteExactInputSingle and friends; they simulate the swap and revert internally, so call them with eth_call only.
  • Reads — CLPoolManager.getSlot0, getLiquidity, getPoolTickInfo, and CLTickLens.getPopulatedTicksInWord for initialized ticks.

Protocol mechanics: Concentrated Liquidity, Swaps, Settlement, Hooks.

Previous
Gacha