Deposits and withdrawals
A deposit credits your account against an external payment; a withdrawal sends
funds out of that account. Their external form depends on the kernel’s network.
On play, they are records of play credits. On a chain network, they correspond
to token payments confirmed by the blockchain.
This chapter first covers play, then follows a chain deposit from address
registration to the resulting account credit. See
What differs between the three networks
for an overview of their payment arrangements.
On play
On play, the operator records deposits using references from their own books.
No wallet or blockchain transaction is involved. The deposit command explains
this arrangement:
$ juice user deposit
Money on the play network has no addresses to send to.
The operator of this kernel records payments here; there is nothing to send from your side.
Ask the operator to credit your account. They use admin user deposit with a
reference identifying the deposit. A withdrawal likewise updates the kernel’s
records without making an external payment. These credits have no real monetary
value, allowing you to learn and test the system without handling funds on a
blockchain.
On test and real
On test and real, deposits and withdrawals use the token specified by the
network: a test token on Arbitrum Sepolia, or USDC on Arbitrum One.
The following examples use a local chain to demonstrate the commands and their output. Substitute the addresses returned by your kernel and wallet. The waiting periods described in the prose refer to the shipped networks rather than the local demonstration chain.
The two assets
Your wallet needs the network’s token for the deposit and ETH for the transaction fee. They serve different purposes.
USDC is the unit used for account balances on real. A deposit of
250.00 USDC credits that amount to the account, and a withdrawal pays USDC
back to the registered address. The test network uses a test token with no
real monetary value.
ETH pays the blockchain fee for sending the deposit. This fee is spent by your wallet in addition to the token amount and is not credited to your Juice balance. The kernel pays its own blockchain fees when sending withdrawals.
What you need before you start
Use a wallet configured for the kernel’s chain that can sign a message and send the required token. Message signing proves ownership of your address; the token transfer supplies the deposit.
test |
real |
|
|---|---|---|
| Chain | Arbitrum Sepolia | Arbitrum One |
| The money | a test token, worth nothing | USDC, real dollars |
| Where it comes from | Sepolia ETH from a public faucet; the test token has an open mint anyone may call |
bought or transferred like any other USDC |
If you need test funds, the operator may be able to supply them. Even on test,
an account credit must be supported by a witnessed payment. The operator can
send you tokens or arrange and attribute a payment on your behalf.
Check the token’s contract address before sending a deposit. A token symbol such as USDC does not uniquely identify it. Obtain the exact address from the operator, since the kernel’s deposit instructions do not yet print it. Payments in another token are not credited through this deposit procedure.
Step 1: register the address you will pay from
The kernel attributes a deposit by its sender address. Register the address you will pay from before sending funds, proving control by signing the kernel’s registration message with that wallet:
$ juice user address 0x70997970C51812dc3A010C7d01b50e0d17dc79C8
Sign this message with the wallet holding 0x70997970C51812dc3A010C7d01b50e0d17dc79C8:
juice address registration
kernel: qjMgb3LBOwxV…
user: cfeacc90-…
address: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8
Signature:
Copy the complete message into your wallet’s message-signing function, then paste the resulting signature at the prompt. The response confirms the registered address and lists any held deposits attributed to it:
address: 0x70997970c51812dc3a010c7d01b50e0d17dc79c8
attributed: []
A program supplies the signature with --signature instead of being asked. If you
work at a command line, cast wallet sign --private-key … "$MESSAGE" produces the
same thing.
An address can be registered to only one account. Registering a replacement changes the destination of future withdrawals; an existing withdrawal retains the address recorded when it was requested.
Step 2: find out where to send
$ juice user deposit
Send real to this kernel at:
0xcaf2a882af8730c6ad92d76361b1952c71c0453f
Pay from your registered address:
0x70997970c51812dc3a010c7d01b50e0d17dc79c8
Money is credited to whoever finally sent it, so it must arrive from that address.
An exchange paying this kernel on your behalf would be crediting itself, not you:
withdraw to your own wallet first, then pay from there.
You can also run this command before registration. It will report that a sender address still needs to be registered.
Step 3: send the USDC
From your own wallet, on that chain, send USDC to the kernel’s address. You pay the transaction fee in ETH, as you would for any transfer.
Select the network’s USDC token as the asset to send. Your wallet will also spend ETH on the transaction fee, but ETH sent directly to the kernel supplies its fuel and does not credit your account.
Send from your registered address. A direct withdrawal from an exchange names the exchange as sender, leaving the payment held for attribution. Withdraw to your own wallet first, then send the deposit from that wallet.
Check that the wallet is using the kernel’s chain. A payment on another chain will not be recognized as a deposit by this kernel.
Step 4: wait
After sending the token, the kernel detects the payment and waits for the network’s required confirmation. It then credits the account registered to the sender address without a further command from you.
The shipped test world accepts a payment once it is included in a block.
The real world waits for finality, so confirmation takes longer. Actual
waiting times depend on the chain and the kernel’s progress reading it.
$ juice user me
available: 250.00 USDC
…
If the expected credit has not appeared, check that the payment used the right chain, token, destination, and registered sender. The operator can inspect held payments and the kernel’s view of chain progress.
Taking money out
$ juice user withdraw 50
Withdraw 50.00 USDC on real to 0x70997970c51812dc3a010c7d01b50e0d17dc79c8, acting as alice@bank? This cannot be undone. [y/N] y
id: 58e1e97f-…
kind: payout
amount: 50.00 USDC
credit: 50.00 USDC
destination: 0x70997970c51812dc3a010c7d01b50e0d17dc79c8
status: submitted
created_at: 2026-09-15T00:12:42Z
party_handle: alice
On a chain network, the withdrawal reserves the amount from your balance and
uses your registered address as its destination. The kernel sends and confirms
the payment automatically. On play, the same operation completes through the
manual payment records. Use user withdrawals to follow the outcome:
$ juice user withdrawals
id: 58e1e97f-…
kind: payout
amount: 50.00 USDC
credit: 50.00 USDC
…
A withdrawal begins as pending, becomes submitted after submission to the
rail, and reaches confirmed when payment is final. A finalized failure returns
the reservation to your balance. The blocked status means the kernel cannot
currently proceed, as described below.
Withdrawals cannot be undone or recalled. Check the destination in the confirmation line before answering it.
For unattended withdrawals, --yes supplies the confirmation in advance.
This is the same convention used for local transfers. Calls to value-bearing
actions differ: issuing run itself authorizes the value named in its input.
When a payment does not go out
A kernel that cannot pay reports it on the withdrawal itself:
status: blocked
reason: native currency too low, top up: holding 0.00, a refill costs 0.002306…
— send native currency to 0xcAf2a882aF8730C6ad92D76361b1952C71C0453F
In this example, the kernel lacks enough ETH to pay its transaction fees. The withdrawal remains reserved and is retried when the cause clears; you should not submit a second withdrawal to replace it. The operator can inspect and address the cause using the procedures in Money on a chain.
Other causes include the cost of a fuel purchase or insufficient operator funds for it. A halt affects outgoing rail work, while deposits, calls, and reads continue.