Enclave is now The Interfold.
Run a Ciphernode
Manage Tickets

Manage Tickets

This page gives the procedures to buy, check, and redeem the tickets of a ciphernode. It is for the bond owner of a registered operator. At the end, you can change the ticket balance with the CLI or with contract calls, and you know which errors stop each step.

For the concepts behind tickets, read Tickets and sortition. For every flag, see interfold ciphernode tickets.

Before you start

You need these items:

  • A registered operator. addTicketBalanceFor reverts with NotRegistered before registration. See Registration.
  • The bond owner wallet, with the ticket collateral and ETH for gas.
  • For the CLI: an interfold configuration whose wallet is the bond owner. The examples use /path/to/owner.yaml. The ticket commands send each transaction from the wallet of the configuration. The --operator flag selects the operator position.

If the operator is its own bond owner, use the node configuration and omit --operator. The CLI then uses the address of the configured wallet. If the bond owner is a Safe, use the contract calls through the Safe interface.

On Sepolia, the fee token and the ticket collateral are the same token: MockUSDC, a test USDC that anyone can mint. The faucet sends tokens to the wallet of the configuration, so use the bond-owner configuration: interfold --config /path/to/owner.yaml faucet --chain sepolia. One call gives 1000 USDC and 1000 FOLD, which is enough for the 100 FOLD Sepolia bond. You can also call faucet() on the Faucet contract from the bond owner, or call mint on MockUSDC.

The --amount values are token amounts, not ticket counts. tickets buy takes an amount of ticket collateral. tickets burn takes an amount of tFOLD. The CLI converts the value with the decimals of the token, so --amount 1000 means 1,000 whole tokens.

Check the ticket balance

Run the status command for the operator:

interfold ciphernode status --operator 0xOPERATOR

Add --chain <name> when the configuration has more than one chain. Without --chain, the CLI uses the first chain entry. The output has this format:

Ciphernode status on mainnet:
  Operator key: 0xOPERATOR
  Bond owner: 0xBOND_OWNER
  Registered: true
  Active: true
  Exit pending: false
  Ticket balance: 2000 (2 available)
  Ciphernode bond: 32000
  Pending exits: tickets=0, bond=0
  Requirements: minTickets=1, ticketPrice=1000 tFOLD, ciphernodeBond=32000 FOLD
  Committees: none
FieldMeaning
Ticket balanceThe tFOLD balance in token units. The number in parentheses is availableTickets.
ActiveThe result of isActive(operator). See When a ciphernode is active.
Exit pendingtrue while a deregistration waits for its exit delay.
Pending exitsTicket collateral and FOLD in the exit queue that the bond owner did not claim yet.
RequirementsThe live minTicketBalance, ticketPrice, and requiredCiphernodeBond.
CommitteesThe committees that hold the collateral until releaseCommittee(e3Id). Each line shows the E3 ID, the membership, and the E3 stage.

The ticket and exit values are also available from BondingRegistry with getTicketBalance(operator), availableTickets(operator), pendingExits(operator), and previewClaimable(operator). For the balance that an E3 used, call getTicketBalanceAtBlock(operator, timepoint) with the requestBlock - 1 timepoint of that E3.

Buy tickets

To calculate the deposit, multiply the number of tickets by ticketPrice. For example, 2 tickets on mainnet at 1,000 sUSDS shares each need a deposit of 2,000 sUSDS shares. A remainder below one ticketPrice stays in the balance but does not give a ticket.

Read the ticket price

Run interfold ciphernode status --operator 0xOPERATOR.

Read ticketPrice in the Requirements line.

Deposit the collateral

Run the buy command from the bond owner configuration:

interfold --config /path/to/owner.yaml ciphernode tickets \
  --operator 0xOPERATOR buy --amount 2000

The CLI reads the ticket token and its collateral token from BondingRegistry. If the allowance is too low, the CLI first approves the ticket token contract for the amount. Then it calls addTicketBalanceFor(operator, amount). The output shows the new ticket count, read back from the chain:

Deposited 2000 <SYMBOL> for operator 0xOPERATOR. Ticket balance is now 2 tickets (tx: 0x…)

Verify the status

Run interfold ciphernode status --operator 0xOPERATOR.

Make sure that Active is true and that the available ticket count is correct.

Redeem tickets

A redemption has three parts. The burn removes the tickets at once. The collateral then waits in the exit queue for exitDelay. After the delay, a claim pays the collateral to the bond owner.

⚠️

A burn takes effect in the same transaction and you cannot cancel it. If the balance drops below minTicketBalance, the operator becomes inactive and cannot enter new committees. The collateral in the exit queue stays slashable until the claim.

Burn the tickets

Run the burn command from the bond owner configuration. The amount is in tFOLD units:

interfold --config /path/to/owner.yaml ciphernode tickets \
  --operator 0xOPERATOR burn --amount 1000

The CLI calls removeTicketBalanceFor(operator, amount). The registry burns the tFOLD and queues the same amount of collateral for exitDelay seconds. The output shows the new ticket count:

Burned 1000 tFOLD from operator 0xOPERATOR. Ticket balance is now 1 tickets (tx: 0x…)

interfold ciphernode deactivate --tickets <amount> sends the same transaction.

Wait for the exit delay

Run interfold ciphernode status --operator 0xOPERATOR to see the Pending exits amounts.

To see the amount that is ready now, call previewClaimable(operator) on BondingRegistry.

Claim the collateral

Run the claim command:

interfold --config /path/to/owner.yaml ciphernode bond \
  --operator 0xOPERATOR claim --max-bond 0

--max-bond 0 claims only ticket collateral. Any account can send this claim, and the collateral always goes to the bond owner. Without --max-ticket and --max-bond, the command claims all the unlocked ticket collateral and FOLD, and only the bond owner can send it. The output is Claimed exits for operator 0xOPERATOR (tx: 0x…).

The contract call for the claim is claimExitsFor(operator, maxTicketAmount, maxCiphernodeBondAmount) on BondingRegistry. To claim everything with a contract call, the bond owner sets both maximums to the largest uint256 value.

The Manage the position section of the hosted operator guide (opens in a new tab) burns tickets and claims the collateral from a browser wallet.

Keep the balance healthy

  • Deposit before demand. An E3 uses the balance at requestBlock - 1. A deposit counts only for E3s that are requested after the deposit block.
  • Keep a margin above the minimum. A ticket slash burns tFOLD from the active balance first. A governance increase of ticketPrice also reduces the ticket count of the same collateral. Either change can make the operator inactive.
  • Match tickets to capacity. The node takes part in at most one E3 for each ticket at the same time. More tickets let the node serve more E3s in parallel, so the host needs the resources for them. See Requirements.
  • Watch the events. TicketBalanceUpdated reports each balance change, and OperatorActivationChanged reports each change of the active status.

Errors

ErrorCauseAction
NotRegisteredThe operator is not registered.Register the operator first.
NotBondOwner(caller, operator)The wallet that sent the transaction is not the bond owner.Use the bond owner configuration or wallet.
ExitInProgressA deregistration waits for its exit delay.Wait until the exit delay ends.
OperatorUnderSlashA slash proposal against the operator is open.Wait until the proposal is executed, cancelled, or expired.
InsufficientBalanceThe burn amount is larger than the tFOLD balance.Burn a smaller amount.
ZeroAmountThe amount is 0.Use an amount larger than 0.
ExitNotReadyNo queued amount is unlocked yet.Wait for the exit delay, then claim again.
OperatorInActiveCommitteeThe operator is on a committee whose E3 is not terminal yet.Wait until the E3 completes or fails and the committee is released.
Fractional precision exceeds token decimalsThe CLI amount has more decimal places than the token.Use fewer decimal places.

Next steps