Selinos
Protocol

Value flow

Two paths run through the protocol. Purchase money goes from a buyer to the payments wallet and ends there. Payout money goes from Selinos’s treasury, through the distributor, onto node balances and out through withdrawals. The two never mix, and only the second can ever reach a holder.

Two pots, kept apart

PotHoldsCan pay holders
Payments walletNode purchases, received as plain transfersNo. It is an ordinary account outside the contract entirely.
Factory balancePayout money, sent by the distributor with creditBatch, plus anything added through fund() or a plain transferYes. This is the only balance a withdrawal draws from.

The separation is not a policy, it is a consequence of where the money is sent. Buying a node is a transfer to a wallet; the factory has no payable mint and never sees your 0.6 HYPE, not for one block. Purchase money cannot become payout liquidity because it is never in the contract to begin with.

Payout money arrives the other way round, from the distributor, and it arrives attached to specific nodes. If the two shared an address every payout would be partly funded by the next buyer and the contract could not tell them apart. Keeping them separate is what gives outstanding and freeBalance() a meaning that can be checked from outside.

The path, hop by hop

Selinos treasuryPaymentA plain transfer tothe payments walletWatcherSees the transfer andrecords the tx hashmintForThe relayer createsthe node, pays the gascreditBatchThe distributor sendsHYPE onto balancesNode balanceHeld on chain,counted in outstandingwithdrawYou call it yourself,the whole balance moves
Purchase on the left, payout on the right. The branch dropping into creditBatch is Selinos's treasury, the only source of credited value.
  1. Payment. The buyer sends exactly 0.6 HYPE to the payments wallet. Plain transfer, no calldata, no contract involved. That money has left the flow at this point: it funds the operation, and nothing downstream draws on it.
  2. Watcher. The server reads blocks, finds the transfer, and records it with its transaction hash before anything is minted. See Deploying a node.
  3. mintFor. The relayer creates the node for the paying address and pays that gas itself. The payment transaction hash goes in as paymentRef, which is what ties the sale to the node in the explorer.
  4. creditBatch. The distributor sends the round’s HYPE and the per-node amounts in one payable call. msg.value must equal the sum of the amounts, so the money and the record land together. See Distribution.
  5. Node balance. The value now sits in the factory, attached to your node and counted in outstanding. It stays there until you move it. Nobody else can, including the contract owner.
  6. withdraw. You call it yourself, from the wallet that owns the node, naming any destination. The whole balance of that node moves. withdrawAll does the same across every node you own in one transaction. See Withdrawing.

Where the payout value comes from

The treasury is not a contract. It is Selinos’s own funds, which top up the distributor’s float, and the distributor sends them into the factory attached to a creditBatch call. HYPE can also reach the factory through fund() or a plain transfer, but that lands as unattached balance and belongs to no node until a credit assigns it. How often nodes are credited and how the amounts are drawn is on How accrual works.

Who pays what

CostPaid byWhen
0.6 HYPE node priceYouOnce, as a transfer to the payments wallet
Gas for the transferYouWith the payment
Gas for mintForSelinos, from the relayerWhen your node is created
Gas for creditBatch, and the HYPE it carriesSelinos, from the distributorEvery round
Gas to withdrawYouEvery withdrawal

Checking the flow yourself

A handful of reads describe the state of the payout pot at any moment, and none of them require this website.

cast
cast call $FACTORY "totalDistributed()(uint256)"  # every wei ever credited to nodes
cast call $FACTORY "totalWithdrawn()(uint256)"    # every wei owners have taken out
cast call $FACTORY "outstanding()(uint256)"       # credited, not yet withdrawn
cast call $FACTORY "freeBalance()(uint256)"       # balance above what is owed
cast call $FACTORY "isSolvent()(bool)"

cast balance $FACTORY                             # the pot itself

outstanding is the sum of every node balance, and freeBalance() is what is left over. Those two are the whole guarantee: rescue is bounded by the second, so no sequence of owner calls reaches the first. If isSolvent() ever returns false the contract is not holding enough to cover the balances it has written, which is a state worth watching for and is listed among the failure modes on Risks.