When SOROBAN_ENABLED is flipped to false, the backend stops interacting with
the Stellar escrow contract. Any escrows that were already created on-chain but
not yet resolved (AWAITING_CONFIRMATION status in the database) will remain
locked on-chain indefinitely.
The backend will log a startup warning if it detects unresolved escrows while Soroban is disabled. This runbook describes how an operator can manually resolve them.
-
Stellar CLI installed:
# macOS brew install stellar-cli # Or via Cargo cargo install --locked stellar-cli
-
Access to the treasury/operator secret key (
STELLAR_SECRET_KEYfrom.env). -
The contract ID (
STELLAR_ESCROW_CONTRACT_IDfrom.env). -
The network passphrase (
STELLAR_NETWORKfrom.env).
Query the database for payments stuck in AWAITING_CONFIRMATION on the Stellar rail:
SELECT id, rail, status, metadata
FROM payments
WHERE rail IN ('STELLAR_CUSTODIAL', 'STELLAR_EXTERNAL')
AND status = 'AWAITING_CONFIRMATION';For each result, compute the escrow ID (SHA-256 of the payment UUID in hex).
Verify the current state of each escrow on-chain:
stellar contract invoke \
--id $STELLAR_ESCROW_CONTRACT_ID \
--network-passphrase "$STELLAR_NETWORK" \
--rpc-url $STELLAR_RPC_URL \
--source $STELLAR_SECRET_KEY \
-- \
get_status \
--escrow_id $ESCROW_ID_HEXExpected return values:
1— Locked (still holding funds, can be released or refunded)2— Released (already sent to beneficiary)3— Refunded (already returned to payer)
If the status is already 2 or 3, you only need to update the database record.
stellar contract invoke \
--id $STELLAR_ESCROW_CONTRACT_ID \
--network-passphrase "$STELLAR_NETWORK" \
--rpc-url $STELLAR_RPC_URL \
--source $STELLAR_SECRET_KEY \
-- \
release \
--escrow_id $ESCROW_ID_HEXstellar contract invoke \
--id $STELLAR_ESCROW_CONTRACT_ID \
--network-passphrase "$STELLAR_NETWORK" \
--rpc-url $STELLAR_RPC_URL \
--source $STELLAR_SECRET_KEY \
-- \
refund \
--escrow_id $ESCROW_ID_HEXAfter resolving each escrow on-chain, update the corresponding payment record:
-- If released:
UPDATE payments SET status = 'CONFIRMED' WHERE id = '<payment-uuid>';
-- If refunded:
UPDATE payments SET status = 'REFUNDED' WHERE id = '<payment-uuid>';Re-run the query from Step 1 to confirm no unresolved escrows remain. Restart the backend — the startup warning should no longer appear.