IntegrationEnglish
Errors
Every revert reason and what it means
Every refusal produces a sentence a human wrote and at least one next step. Never a selector, an address, a function name, or a library's raw output.
Declare every error in your ABI
A custom error decodes only when it is declared in the ABI you use. An error missing from your ABI produces no message at all, and the interface falls back to "the transaction failed", with no cause and no remedy, after the user spent gas.
The stronger form of that rule:
Every rule the contract enforces is known to the interface before the send, not translated after the refusal.
Read youngWalletCap, youngReserveThreshold, positionCost, minBuyCost and maxBuyCost, clamp the amount field to the room available, and block the impossible order. A contract gaining a rule gives an interface three things: the read, the guard, the message.
Market
| Error | Cause | Message |
|---|---|---|
PositionTooSmall | Reserve cost below minBuyCost, 1 USD | "Minimum position is 1 USD. Raise the amount a little." |
TradeTooLarge | Reserve cost above maxBuyCost | "This order is larger than the market allows right now. Try a smaller amount." |
YoungMarketWalletCap | positionCost + reserveCost exceeds youngWalletCap while the reserve sits under youngReserveThreshold | "While a market is young, one wallet holds at most 1,000 USD here. You can still add X." |
SlippageExceeded | Real cost above maxTotalCost, or proceeds below minNetProceeds | "The price moved while your order was being sent. Nothing was charged. Try again." |
Expired | block.timestamp > deadline | "The 5-minute window closed before the order went through. Nothing was charged. Try again." |
InsufficientClaims | Selling more claims than held, or than the supply | "You no longer hold enough claims for this sale. Refresh and try again." |
PurchasesPaused | buysPaused is true | "Purchases are temporarily blocked. Selling still works." |
EnforcedPause | The market is paused | "This market is temporarily paused." |
InvalidAmount | Zero claims | Block it before sending |
OnlyFactory | buyFor called by anything but the factory | Integration bug |
InvalidConfiguration | Bad init params, or setTalent(address(0)) | Integration bug |
Factory
| Error | Cause |
|---|---|
MarketAlreadyExists | The profile already has a market. Ask the chain before offering to create one |
FirstPositionRequired | firstPositionClaims == 0. A market opens with a position |
UnknownMarket | buyOnMarket pointed at a contract this factory did not create. This guard stops anyone draining the allowance traders grant the factory |
InvalidAddress | Zero address in an admin setter |
InvalidPreset | Fee above 10 %, a zero ceiling or minimum, a wallet cap above the reserve threshold, a flat amount above 1,000 USD, an inverted creator ramp, or creator + referrer shares above 100 % of the fee |
Curve
| Error | Cause |
|---|---|
SupplyOutOfRange | Above the uint256 overflow guard, ~4.87e25 micro-claims, or selling more than the supply. A clean revert instead of a wraparound |
Referral registry
| Error | Cause |
|---|---|
SelfReferral | account == referrer |
InvalidAddress | Zero address on either side |
Access control
AccessControlUnauthorizedAccount(account, role), from OpenZeppelin. The caller lacks DEFAULT_ADMIN_ROLE, PAUSER_ROLE or OPERATOR_ROLE.
Token and wallet
The failures users hit most, none of them ours:
| Situation | Message |
|---|---|
| Allowance too low | "The approved spending limit is too low. Approve again, keeping the suggested amount." |
| Insufficient balance | "Insufficient balance for this operation." |
| No ETH for gas | "You need a little ETH to pay network fees." |
| Rejected in the wallet | "Transaction cancelled in the wallet." |
| Wrong network | "Your wallet is on the wrong network." Offer the switch, and a manual fallback for wallets that refuse programmatic switching |
| RPC silent | "The network did not answer. Nothing was sent and your balance is untouched." |
| Sent, unconfirmed | "Transaction sent but not confirmed yet. Open the proof, then reload." Never re-offer the payment |
The two absolutes
- A confirmed payment never asks to pay again. Between on-chain confirmation and indexing, the screen becomes a receipt (proof plus a wait), and the pay button disappears. It survives a page reload, because "does this market already exist?" is asked of the chain, not of a database.
- Every failure carries a next step. Retry, switch network, sign again, disconnect, add gas. A frozen button with no explanation is a bug, not a state.