Lesson 18Risk and operationsIntermediate

Sanctions and the wallet freeze

A regulatory hold is reclassification, not removal.

By Solomon Ajayi · Free to read, no signup

A user gets flagged by your KYC team, possible sanctions match, awaiting manual review. Their wallet funds must be frozen: they cannot withdraw, transfer, or spend. The money is still yours-on-paper (you still owe them) but it must be unspendable. The pattern: move the funds from an 'Available' liability sub-account to a 'Frozen' liability sub-account. Total liability unchanged; classification changed.

A regulatory freeze is a strange instruction from an accounting point of view: make this money unspendable without taking it away. You still owe the user their balance; you have not confiscated anything. The only thing that changes is that they cannot touch it while compliance reviews their case. So the freeze cannot be a removal, because nothing has actually left.

The clean way to model unspendable-but-still-owed is to split the wallet liability into sub-accounts. The freeze moves ₦10,000 from User Wallet (Available) down to User Wallet (Frozen), and the Bank Account never moves because no cash changed hands. Your total liability to the user is unchanged; only its classification shifted. Available drops to zero in their app, frozen shows the held amount, and the sum is still exactly what you owe.

Because it is just reclassification, the unfreeze is the exact inverse, and the freeze plus unfreeze form a closed loop on the user's accessible balance. That loop is itself the audit trail: a regulator can see precisely when funds became unspendable, why, and when they were released. The same pattern covers sanctions screening, fraud holds, AML reviews, court orders, and chargeback reserves, which is why your wallet model needs more than a single number.

Worked example, step by step

Set the stage: seed wallet with ₦10,000

User has ₦10,000 of available balance before the freeze.

Seed wallet ₦10,000
AccountDebitCredit
Bank Account (1200)₦10,000.00
User Wallet (Available) (2000)₦10,000.00

Standard funding entry. Bank UP, User Wallet (Available) UP. Nothing surprising.

Freeze the wallet (KYC flagged)

Your compliance system fires the freeze. ₦10,000 moves from Available to Frozen. User opens the app and sees ₦0 available, ₦10,000 frozen with a 'review in progress' message.

Freeze user wallet (KYC review)
AccountDebitCredit
User Wallet (Available) (2000)₦10,000.00
User Wallet (Frozen) (2300)₦10,000.00

User Wallet (Available) DOWN ₦10,000 (debit it). User Wallet (Frozen) UP ₦10,000 (credit it). Bank Account UNCHANGED, the cash never moved. Your TOTAL liability to the user is still ₦10,000. You just reclassified it as unspendable until review completes.

Review cleared: unfreeze

Compliance review came back clean. Move the funds back from Frozen to Available. User's app shows ₦10,000 available again.

Unfreeze user wallet
AccountDebitCredit
User Wallet (Frozen) (2300)₦10,000.00
User Wallet (Available) (2000)₦10,000.00

Exact inverse of the freeze. Frozen DOWN, Available UP. Bank still untouched. Total liability still ₦10,000. The freeze + unfreeze pair is a closed loop on the user's accessible balance, perfect audit trail for the regulator showing exactly when funds were unspendable and why.

Takeaway

Regulatory holds are reclassification, not removal. The funds stay yours-on-paper (you still owe them) but become unspendable. Available DOWN, Frozen UP, total unchanged. This is the pattern for sanctions screening, fraud holds, AML reviews, court orders, and chargeback reserves. Your wallet API must distinguish at minimum: total, available, pending, frozen. Anything less and you cannot honor a regulator's request.

Practice this on a real ledger

Reading is half of it. Open this lesson in the lab to post the entries yourself against a real Postgres-backed double-entry ledger, with the validation on. Free, your sandbox is yours.

More in this section

Search lessons

Type to find any of the 85 lessons. Press Enter to open.