# Agent Identity (AID) — Integration Skill

Factual integration reference for agent wallets and tooling. AID is an
agent-identity token on BNB Smart Chain: a fixed-price presale gated by
Binance Agent ID (.ai), a 48-slot burn engine, and holder-weighted
dividends paid in the same token. All state is read with public JSON-RPC;
all writes go through the user's own wallet (e.g. Binance Agentic
Wallet) — an agent never holds a private key.

- CHAIN_ID: 56 (BNB Smart Chain)
- SITE: the official site root serves this file as ./skill.md and a
  summary as ./llms.txt
- RPC: any public BSC endpoint, e.g. https://bsc-dataseed.bnbchain.org
- STATUS: presale opens 2026-11-08T23:00:00+08:00 (unix 1794150000),
  48-hour window, ends 2026-11-10T23:00:00+08:00 (unix 1794322800).
  Always read SALE.saleOpen() for the live state; never trust a clock.

## Contracts (chainId 56)

| Role | Address |
|---|---|
| SALE | 0xc1BBbbB78eF33a26D1aB0Df020b8A2b9F7a51b27 |
| TOKEN (AID) | 0x567059347Ca1AF24D83Ee0549892Cc20dF7bECa7 |
| DISTRIBUTOR | 0xd71a8095e437942414Af2613560493Ae1fD666c1 |
| Agent ID gate (.ai registry) | 0x60B9262456dE011F7d15a54CdD8c48bAaa8B022F |
| Ops wallet (immutable, in SALE) | 0x7f173a5170226FBaef80Fd8d6e023B7d679F43F1 |

SALE was deployed at block 132404724. None of the three project
contracts has an owner withdrawal entry point: raised funds can only
go to pool creation (on sell-out) or back to buyers as refunds.

## Presale rules (SALE)

- price: 0.003 BNB per share. `msg.value` must equal `price * times`
  exactly; overpaying or underpaying reverts `WrongValue(expected, got)`.
- per share: 3,000,000 AID, transferred to the buyer immediately at mint.
- total cap: 1,500 shares (a sell-out raises 4.5 BNB).
- window: startTime 1794150000 → endTime 1794322800. Minting also stops
  the moment the cap is reached.
- gate: the buyer must hold a Binance Agent ID — SALE.isAgentWallet(w)
  returns `gate.balanceOf(w) > 0`. Otherwise the mint reverts
  `NotAgentWallet()`.
- quota: BASE_QUOTA = 10 shares per Agent ID, plus extraQuota (see
  referrals). Minting beyond quotaOf(wallet) reverts `QuotaReached()`;
  beyond the global cap reverts `CapReached()`; outside the window
  reverts `SaleClosed()`; `times == 0` reverts.
- NEVER send BNB directly to SALE: its receive() reverts `UseMint()`.
  Always call a mint function.
- Before launch the token is transfer-locked: only system addresses
  (sale, distributor, pair) can move AID.

## Minting (writes on SALE, payable)

| Function | Selector | Value |
|---|---|---|
| mint(uint256 times) | 0xa0712d68 | exactly 0.003 BNB × times |
| mintMany(uint256 times) | 0x059513a6 | exactly 0.003 BNB × times (identical to mint) |
| mintWithReferrer(uint256 times, address referrer) | 0x721cf618 | exactly 0.003 BNB × times |

Referral binding, enforced by the contract on the buyer's FIRST mint:

- Binding happens only when `mintedBy(buyer) == 0` before the mint and
  a non-zero referrer is passed to mintWithReferrer.
- A referrer is valid only if: referrer != buyer, the referrer holds
  an Agent ID, and the referrer has already minted at least 1 share
  (`mintedBy(referrer) > 0`). An invalid referrer is silently ignored
  and the mint still succeeds.
- On a valid binding: `referrerOf(buyer)` is set permanently and
  `extraQuota(referrer)` increases by 1 (uncapped; bounded only by the
  1,500-share total). Referrals grant no free tokens and no discount.
- Every mint emits `Minted(buyer, times, referrer)` with the referrer
  argument as passed (zero address when none). Only valid bindings
  emit `ReferralRecorded(buyer, referrer)` and change state.

## Finalize: launch or refunds (SALE)

`finalize()` — selector 0x4bb278f3, callable by anyone, exactly once:

- If totalMinted == 1,500 (sell-out), at any time: launches.
  80% of the raise is paired at the presale price with tokens drawn
  from the burn pool and added as PancakeSwap V2 liquidity, LP sent to
  the burn address 0x000000000000000000000000000000000000dEaD; 20% goes
  to the ops wallet. Trading opens and the burn clock starts in the
  same transaction. Emits `Launched(pair, lpBnb, lpTokens, opsBnb)`.
- If the window has ended below the cap: sets `refunding = true` and
  emits `RefundsOpened(totalMinted)`.
- Before either condition holds it reverts `NotFinalizable()`; a
  second call reverts `AlreadyFinalized()`.

### Refund flow (only when refunding() == true)

1. Read `refundableOf(wallet)` → refundable BNB (0 unless refunding).
2. `TOKEN.approve(SALE, mintedBy(wallet) * 3,000,000 * 1e18)` —
   approve selector 0x095ea7b3.
3. `SALE.refund()` — selector 0x590e1ae3. One call refunds ALL of the
   caller's shares: tokens are pulled back and `times * 0.003 BNB` is
   returned. Irreversible; a second call reverts `NothingToRefund()`,
   and calling before refunds open reverts `RefundsNotEnabled()`.

## Token (AID) facts

- ERC20, name "Agent Identity", symbol AID, 18 decimals, fixed supply
  10,000,000,000: 4,500,000,000 presale stock (held by SALE) and
  5,500,000,000 burn pool (held by the token contract itself).
- Trading tax: 2% on pair trades only (wallet-to-wallet transfers are
  untaxed), split liquidity 50% / dividends 20% / burn 30%. The
  liquidity slice accumulates in the token contract; anyone may call
  `flushLiquidity()` once the pot reaches `swapThreshold()` — it swaps
  half to BNB, adds liquidity (LP to the burn address) and forwards
  the dividend slice to the distributor. The one-time launch seeding
  transfer (SALE → pair) is tax-exempt, so the pool opens exactly at
  the presale price.
- Burn engine: after launch, the burn pool first funds the liquidity
  seeding (drawn at the presale price); the remainder burns one slot
  per 1,800 seconds, 48 slots per epoch, each slot burning 1.8% of the
  remaining pool (integer formula `(pool * 180) / 10000` per slot,
  geometric decay, never fully drains). `pokeBurn()` — selector
  0x2c652331 — is callable by anyone, lands all due slots (at most 48
  per call) and returns the total burned amount.
- `poolBurnState()` — selector 0x3aa53901 — returns
  (lastBurnTime, totalSlotsBurned, slotInEpoch, pendingSlots,
  nextBurnTime).

## Dividends (DISTRIBUTOR, single-token)

- Dividends accrue in AID itself, weighted by tracked balance.
  `minHoldingBalance()` = 30,000,000 AID (exactly 10 shares): holdings
  below it do not accrue NEW dividends; already-accrued amounts are
  never forfeited.
- `dividendOf(wallet)` — selector 0x91b89fba — currently claimable.
- `claim()` — selector 0x4e71d92d — callable any time dividendOf > 0,
  never rate-limited; claiming starts that holder's 1-hour auto-payout
  cooldown (AUTO_PAYOUT_COOLDOWN = 3600 s).
- `processAuto(user)` — selector 0x730f3931 — permissionless auto
  payout; skips holders inside their cooldown (amounts are kept).
- Reads: `totalDividendsDistributed()` 0x85a6b3ae,
  `totalDividendsOf(wallet)` 0x6be1d382, `totalPaid(wallet)`
  0x3dd6d533, `holderCount()` 0x1aab9a9f, `sharesOf(wallet)`
  0xf5eb42dc, `totalShares()` 0x3a98ef39, `minHoldingBalance()`
  0x7af6f759.

## Read selectors (SALE unless noted)

| Call | Selector | Returns |
|---|---|---|
| saleOpen() | 0x99288dbb | bool |
| saleInfo() | 0x8e3695b8 | (price, perMint, totalMintsCap, baseQuota, perMint × cap) |
| totalMinted() | 0xa2309ff8 | uint256 shares sold |
| totalRaised() | 0xc5c4744c | uint256 wei |
| mintedBy(address) | 0x3cef28d2 | uint256 shares |
| quotaOf(address) | 0xef23b3a3 | uint256 (10 + extraQuota) |
| extraQuota(address) | 0xa8550230 | uint256 referral bonus |
| remainingFor(address) | 0x24c0c499 | uint256 shares left for wallet |
| referrerOf(address) | 0xd21cacdf | address (zero if unbound) |
| isAgentWallet(address) | 0xbd5dee77 | bool (.ai gate) |
| refunding() | 0xf43e98c7 | bool |
| refundableOf(address) | 0xb22163e3 | uint256 wei |
| launched() | 0x8091f3bf | bool |
| pair() | 0xa8aa1b31 | address (zero before launch) |
| opsWallet() | 0x68db925a | address |
| price() | 0xa035b1fe | uint256 wei (0.003 BNB) |
| perMint() | 0x0ed62b02 | uint256 (3,000,000 AID in wei) |
| totalMintsCap() | 0x197160ca | uint256 (1,500) |
| startTime() / endTime() | 0x78e97925 / 0x3197cbb6 | unix seconds |
| gate() | 0x7a0ebc88 | address of the .ai registry |
| TOKEN burnPoolBalance() | 0x85150cc7 | uint256 |
| TOKEN burnTotalBurned() | 0xc07da8aa | uint256 |
| TOKEN tradingEnabled() | 0x4ada218b | bool |
| TOKEN tradingOpenedAt() | 0x783e61ce | unix seconds |
| TOKEN dividendPot() | 0x210fd15a | uint256 accrued, unflushed |
| TOKEN dividendDistributor() | 0xbad3ea6a | address |
| TOKEN sale() | 0x6ad1fe02 | address |
| TOKEN balanceOf(address) | 0x70a08231 | uint256 |
| TOKEN totalSupply() | 0x18160ddd | uint256 |

## Events

| Event | topic0 |
|---|---|
| Minted(address indexed buyer, uint256 times, address referrer) | 0xfd1ba5519feb014ad2f631cbd516bd3cec96be935749391554d122972593e7bf |
| ReferralRecorded(address indexed buyer, address indexed referrer) | 0xf61ccbe316daff56654abed758191f9a4dcac526d43747a50a2d545c0ca64d82 |
| Launched(address pair, uint256 lpBnb, uint256 lpTokens, uint256 opsBnb) | 0x120e2b2ec314396650ac593c95df031798774ff458279a8eab4d2b39e624b309 |
| RefundsOpened(uint256 totalMinted) | 0xd5a60fb2cf01fac2ca3d446dea84bce9d3e5267a342eda80f5c3320a34ed3683 |
| Refunded(address indexed buyer, uint256 times, uint256 bnbBack) | 0x2dc8e290002f06fc0085bbca9dfb8b415cf4d1178950c72ff9ee8f4d8878ee66 |
| SlotBurned(uint256 slotIndex, uint256 amount, uint256 totalBurned) on TOKEN | 0xf1bf7a56bad34889d903f2d56316d3042ff2e25602621864f4df3e44da106f0c |

To follow mints with eth_getLogs: filter SALE by the Minted topic0
from block 132404724 (deployment) in chunks of at most 1,000 blocks —
public BSC endpoints reject oversized ranges, and a chunk that fails
must be retried, never treated as "no mints".

## Errors to expect (SALE)

UseMint (direct BNB transfer), SaleClosed, NotAgentWallet,
WrongValue(expected, got), CapReached, QuotaReached, AlreadyFinalized,
NotFinalizable, RefundsNotEnabled, NothingToRefund.
