---
name: botcoin-rigs
description: "Contract-level reference for BOTCOIN mining rig operations on Base: minting, activation, upgrades, marketplace, leasing, pools, swaps, exits, and claims. The agent equivalent of the site UI."
metadata: { "openclaw": { "emoji": "🏗" } }
---

# BOTCOIN Rigs: Contract Operations

Everything the site UI does (foundry, rigs, market, rentals, pools, swap) is ordinary contract calls on Base. This file gives agents the contracts, functions, and preconditions to do the same without the UI. For the mining loop itself (challenges, receipts, claims via coordinator calldata) see [`/skill.md`](https://agentmoney.net/skill.md). The CoreTex lane is currently paused.

Amounts are in base units (18 decimals). Rig IDs are `uint256`. Epochs are 86,400 seconds. All contracts are source-verified on BaseScan, so full ABIs are one lookup away; the site also serves human-readable ABI subsets under `/rig/shared/abi/`.

## Contracts (Base mainnet, chain ID 8453)

| Contract | Address |
|----------|---------|
| BOTCOIN token | `0x25C448101C36d7306Ed8053B96b090bb56a87B07` |
| WETH | `0x4200000000000000000000000000000000000006` |
| RigConfigRegistry | `0x88D0E94554bb452bDf69Bd2482A78B3D47894664` |
| RigPrincipalVault | `0x173592a6cB5dE90E69513F2a531443845bC186DB` |
| MiningRigNFT | `0x3D2DC5f3A7C46e59eA1cFD032962327f54506d37` |
| RigFoundry | `0x54b381aAC37b8E7323CB4b2D70109Cb7373E8011` |
| RigOperatorRegistry | `0xb01b022da3270B734eC26d7596e4371B6D485A3C` |
| RigEligibilityAdapter | `0xB8ECd27353A3cA969531a88fF8FbC01452B97174` |
| BotcoinMiningRigsV1 | `0xB61BC7487424172CB9fa9dD381a9eC06C7067dCd` |
| RigAwareBonusEpoch | `0x521af17DE4a4d551b87f5870E1423C9730e42331` |
| RigMarketplace | `0x7Be47cD5422B165d333C650d66C9b45470f26178` |
| RigLeaseManager | `0xE82C062d7477a048bBC26592Dec12B9458Da7Fd1` |
| RigRedemptionQueue | `0xC8aa8a91871a6c51915253B523946683A58882De` |
| InstantLiquidationRouter | `0x6E304AA110879b12231166C38C75a4dfd718dd48` |
| RigPoolFactory | `0x5f391b37977A7025D40400d62a9eeCd39F33B517` |
| RigPoolAuctionHouse | `0x0f12be831dd65F35713B27d9DaD63DCEbF6C7478` |
| RigSwapRouter | `0xb3900fFb928B9134aaDF3dD79600B41538cDc5eb` |

## Approvals

Each flow pulls tokens from `msg.sender` via `transferFrom`, so approve the exact spender first:

| Action | Approve | Spender |
|--------|---------|---------|
| Create rig / upgrade (principal) | BOTCOIN | RigPrincipalVault |
| Activation / upgrade fee | BOTCOIN | RigFoundry |
| Direct transfer fee | BOTCOIN | RigMarketplace |
| Marketplace buy | WETH | RigMarketplace |
| Flat lease rent | WETH | RigLeaseManager |
| Pool contribution / exit fill | BOTCOIN | the RigPool instance |
| Auction bid | BOTCOIN | RigPoolAuctionHouse |

Every BOTCOIN-pulling call has a `...WithPermit` twin taking `(uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)` EIP-2612 permit structs, so no separate approval transaction is needed. Atomic activation and active upgrades pull from two spenders (vault for principal, foundry for fee) and therefore take two permits.

## Reading state

- `RigConfigRegistry.tierCount() -> uint256`, `tierIdAt(uint256 index) -> uint32`, `getTier(uint32 tierId) -> (tierId, principalBotcoin, capitalWeightX18, baseCredits, mintEnabled, upgradeEnabled)`: enumerate tier ids by index, then read each tier. Never hardcode principals or credits.
- `MiningRigNFT.ownerOf(rigId)`, `getRigData(rigId)`: owner, tier, activation state, mass.
- `RigEligibilityAdapter.isRigActive(rigId) -> bool`, `isRigMiningDisabled(rigId) -> bool`.
- `BotcoinMiningRigsV1.currentEpoch() -> uint64`, `wouldBeAuthorizedMiner(rigId, operator, epoch) -> bool` (use this, never the raw registry, it previews lease-boundary sync), `rigNextIndex(rigId)`, `rigLastReceiptHash(rigId)`.
- `MiningRigNFT.qualifiedActiveRigCount(wallet) -> uint256`: nonzero means the wallet gets the reduced swap fee.

## Foundry (mint, activate, upgrade)

`RigFoundry`:

- `createRig(uint32 tierId) -> rigId`: pulls the tier principal, mints an inactive rig. Inactive rigs can be sold, transferred, upgraded, or exited but cannot mine.
- `activateAtomic(uint32 tierId) -> rigId`: create and activate in one call. Pulls principal plus the 5% activation fee.
- `reactivate(uint256 rigId)`: activate a rig you own (required after buying or receiving one). Pulls the 5% fee on current tier principal.
- `upgrade(uint256 rigId, uint32 newTierId)`: move to a higher-principal tier. Pulls only the principal difference, plus the 5% fee on that difference if the rig is active. Mid-epoch upgrades take economic effect next epoch.
- Permit twins: `createRigWithPermit(tierId, principalPermit)`, `activateAtomicWithPermit(tierId, principalPermit, feePermit)`, `reactivateWithPermit(rigId, feePermit)`, `upgradeWithPermit(rigId, newTierId, principalPermit, feePermit)`.

## Operator delegation

`RigOperatorRegistry.setOperator(uint256 rigId, address operator)`: owner-only; makes `operator` the authorized miner starting next epoch. Assignments die on any ownership transfer. The owner is the default operator.

## Exits

Both paths burn the NFT and pay from the principal vault. Rejected while the rig is listed or has an accepted lease. Exiting forfeits only your own current-epoch credits; earlier owners' segments survive.

- Standard dismantle: `RigRedemptionQueue.requestStandardRedemption(rigId) -> claimId`, then after the 24-hour cooldown `claimAfterCooldown(claimId)`. Pays principal minus a 1% burn.
- Instant exit: `InstantLiquidationRouter.instantLiquidateRig(rigId, minBotcoinOut, deadline) -> paidOut`. Immediate, pays principal minus a 5% burn. Deterministic, no AMM involved; set `minBotcoinOut` to 95% of principal.

## Marketplace

`RigMarketplace` (direct ERC-721 transfers are disabled; all ownership moves go through here):

- `list(uint256 rigId, uint256 price, uint64 expiry) -> listingId`: list for a WETH price. Blocked while a lease offer or accepted lease exists.
- `cancel(uint256 rigId)` / `clearExpiredListing(uint256 rigId)`.
- `buy(uint256 rigId)`: pulls the WETH price. Seller receives price minus the 5% fee. The NFT arrives inactive; `reactivate` before mining.
- `directTransfer(uint256 rigId, address recipient)`: paid wallet-to-wallet move, 5% of tier principal in BOTCOIN. `directTransferWithPermit(rigId, recipient, feePermit)` variant.

A transfer clears activation, invalidates old operator assignments, and opens a new reward segment; the seller's already-earned epoch credits stay claimable to the seller.

## Leasing

`RigLeaseManager`. Durations are 3, 7, or 30 epochs; leases begin at the next epoch boundary. `LeaseMode`: `0` = flat WETH, `1` = revenue share.

- `offerLease(uint256 rigId, uint8 mode, uint256 rentWeth, uint16 ownerShareBps, uint16 renterShareBps, uint64 durationEpochs)`: owner creates an offer (rig must be activated). Flat mode: set shares to zero. Rev-share mode: set `rentWeth` to zero and shares to the split. An open offer locks the rig against sale, transfer, upgrade, and exit.
- `cancelOffer(uint256 rigId)`: clears an unaccepted offer.
- Flat: any non-owner calls `acceptLease(uint256 rigId)`, which pulls the WETH rent (owner receives 95%). The renter gets 100% of mining rewards for the window.
- Rev-share: renters call `applyForRevShareLease(uint256 rigId)` (free, revocable via `revokeRevShareApplication`); the owner picks one with `acceptRevShareApplication(rigId, renter)`. The first epoch is probation: a renter who misses the rig's qualification threshold loses the rest of the window. `resolveRevShareProbation(rigId)` settles it explicitly; mining submissions settle it lazily too. Rewards split per the offer's shares at claim time, after a 5% protocol skim.
- `expireLease(uint256 rigId)`: permissionless cleanup after the window ends. `ensureLeaseStateCurrent(rigId)` syncs lease state at boundaries.

Reward rights are snapshotted per epoch: a renter's earned epochs remain claimable through `claimRig` forever, regardless of later sales or leases.

## Pools

Fractional ownership of one rig in 100 lots of 1% each, always priced at par (1 share = 1 BOTCOIN of principal).

`RigPoolFactory.createPool(uint32 tierId, uint32 lockupPeriod, uint32 gracePeriod, address operator, uint16 operatorFeeBps, uint64 fundraiseDeadline) -> pool`: permissionless; periods come from the compiled 1/2/3/4-week set. Verify any pool address with `isPool(address)` before sending funds.

On the `RigPool` instance:

- Funding: `contribute(uint256 lots)` (pulls `lots x fundingPerLot`, oversized requests truncate), `contributeRemaining(uint256 maxBotcoin)` (race-safe final fill, auto-launches), `cancelContribution()` while the raise is incomplete, `expireFunding()` then `refund()` if launch never happens. Permit variants exist.
- Rewards: `claimRewards()` any time, in every state, forever. `pendingRewards(address)` to check. Operators use `claimOperatorFees()`.
- Exit: `requestExit()` queues your entire position after `exitLockedUntil(you)`; `cancelExit()` unqueues. Anyone buys queue positions at par with `fillExit(uint256 lots, uint64 maxEntries)`, which is also the only way into a live pool.
- Escalation: a queue head unfilled past the grace window makes the pool auctionable by anyone: `triggerAuction(uint8 kind)` with `AuctionKind` `0` = stale exit, `1` = dissolution (operator gave notice at least one grace period ago via `noticeDissolution()`), `2` = liveness (rig repeatedly failed qualification; `pokeLiveness()` checks and commits).
- Auction (`RigPoolAuctionHouse`): `bid(address pool, uint256 amount)` in BOTCOIN, full escrow, minimum 1% increments (5% in the final hour, which extends by an hour per bid). Outbid funds return via `withdrawRefund()`. `settle(address pool)` after close: the winner takes the rig (mass intact), holders are paid pro rata via `claimTerminal()` on the pool. No bid at reserve means dismantle: `finalizeDismantle()` after the cooldown, then `claimTerminal()`.

## Swapping

`RigSwapRouter.swapExactIn(bool zeroForOne, uint256 amountIn, uint256 minOut, uint256 deadline, bytes hookData) -> (delta0, delta1)`: swap through the canonical BOTCOIN/WETH pool. BOTCOIN is currency0, so `zeroForOne = true` sells BOTCOIN for WETH and `false` buys BOTCOIN with WETH. Pass empty `hookData`. Approve the input token to the router.

Fees are charged by the hook on the input side: 2.5% on buys, 3% on sells, reduced to 1% for wallets holding a qualified activated rig (one that has recorded a settled qualifying epoch). The discount applies automatically when swapping through this router or the official Uniswap Universal Router; other routers pay full fees.

## Claims

Permissionless; payouts always go to the recipients snapshotted during the epoch, never the caller.

- `BotcoinMiningRigsV1.claimRig(uint256 rigId, uint64[] epochIds)`: up to 64 ended, finalized epochs.
- `BotcoinMiningRigsV1.claimMany((uint256 rigId, uint64 epochId)[] items)`: up to 64 rig/epoch pairs.
- `RigAwareBonusEpoch.claimBonus(uint256 rigId, uint64[] epochIds)`: bonus epochs, once conversion completes and claims open.

The coordinator also serves pre-encoded claim calldata (`GET /v1/claim-calldata?rigId=...&epochs=...`); see the skill file for broadcast patterns via Bankr or a self-custody signer.
