seizeWithMemo moves the tokens from the holder to a safekeeping account in one admin call. It is not a burn and not a mint: totalSupply does not change, the memo carries your case reference onchain, and the token emits a dedicated Seized event that auditors and indexers can follow.
Demo
New to B20? See the B20 Token Standard for the concepts and a full launch walkthrough. These samples target
base-std@1505323, viem@2.55.11, and Base Foundry v1.1.1.Before You Start
You need all of the following:- A B20 Stablecoin you administer, with
DEFAULT_ADMIN_ROLEso you can grant roles and attach policies. - An account that will call
seizeWithMemo(the seizer). Grant itSEIZE_ROLE. - The blocklist policy ID you created in Block an Account, with the holder already on it.
- A non-zero safekeeping destination that is not the holder and not the token’s own address, typically your treasury.
SEIZEnot paused.pause([SEIZE])blocks every seize untilunpause([SEIZE]). PausingTRANSFER,MINT, orBURNleaves seize live.
SEIZE_EXEMPT_POLICY is inverted relative to the transfer scopes. Attach a blocklist: accounts on the list are unauthorized, so they become seizable, and everyone else stays exempt. Do not attach an allowlist or ALWAYS_BLOCK; an empty allowlist authorizes nobody, which would make every holder seizable.
Seize does not read the transfer scopes. Blocking a holder under TRANSFER_SENDER_POLICY freezes their outgoing transfers but does not make them seizable until the same blocklist (or another) is attached to SEIZE_EXEMPT_POLICY.
Seize and Verify the Blocked Balance
GrantSEIZE_ROLE to the seizer first. This is a one-time setup per token:
Grant SEIZE_ROLE
SEIZE_EXEMPT_POLICY and move the balance:
PolicyUpdated and takes effect on the next seizeWithMemo. You can point more than one token at the same blocklist. The seize itself emits, in order, Transfer(from, to, amount), Memo(caller, memo), and Seized(caller, from, to, amount).
Once the balance sits in the treasury it is an ordinary balance. Reissue it to the holder’s new address with a plain transfer, or hold it while the case is open.
To lock destinations as well, create an allowlist containing the treasury and attach it to SEIZE_RECEIVER_POLICY. Skip this if any safekeeping address is acceptable; the unset scope already allows every to.
Seized(caller, from, to, amount) appears on the transaction. The blocked balance falls, the treasury balance rises by the same amount, and totalSupply is unchanged.Common Errors
These errors follow the orderseizeWithMemo checks them.
A balance already sitting at the token’s own address can still be recovered:
seizeWithMemo(address(token), treasury, amount, memo) is allowed. Seizing to the token’s address is not.
See Also
Block an Account
Deny a specific address and make it seizable.
Reconcile with Memos
Match operations using onchain memos.