Regarding the UX concerns introduced by wrappers, I think the ZWToken-unaware workflow can significantly improve the situation. Users don’t necessarily need to be aware that a wrapper exists at all.
I still believe that even if new tokens are issued, wrappers remain the only viable path. Asset issuers generally prefer to avoid regulatory exposure (which is essential for the survival of their projects), so privacy inevitably has to be handled by a permissionless wrapper — even if that means we’ll need some additional UX improvements.
To clarify my previous comment:
I realized that what I’m exploring is not a wrapper-based model and not a dual-mode token.
It is actually a different token primitive, which I’m calling a ZW-Token (Zero-Wrapped Token) for now.
This primitive is based on three invariants:
1. Irreversible, deterministic burn
Supply strictly decreases over time.
Burned units can never re-enter circulation (no unwrap, no remint, no mirrored states).
2. Single-state supply (no private balances, no parallel ledgers)
Privacy does not hold or represent supply.
There is only one global supply counter:
totalSupply = initialSupply – irreversibleBurns
3. Unlinkable transfer layer on top of a single supply
Transfers can be made unlinkable (no A→B traceability) without creating wrapped supply or dual representations of the asset.
This produces a different category of token: supply-bounded, irreversible-burn assets with privacy that does not fragment supply.
It’s not a modification of ERC-8060;
it’s orthogonal to it — a separate primitive that could exist alongside it.
Great proposal. Before native account abstraction arrives, relayers/bundlers are still a necessary component, and the ERC should be able to support various types of relayers.
/// @notice Encapsulates all data required for remint operations
/// @param commitment The commitment (Merkle root) corresponding to the provided proof
/// @param nullifiers Array of unique nullifiers used to prevent double-remint
/// @param proverData Generic data for prover
/// @param relayerData Generic data for relayer, can contain fee information. Hash is used in ZK proof.
/// @param proof Zero-knowledge proof bytes verifying ownership of the provable burn address
struct RemintData {
bytes32 commitment;
bytes32[] nullifiers;
bytes proverData;
bytes relayerData;
bytes proof;
}
/// @notice Remint ZWToken using a zero-knowledge proof to unlink the source of funds
/// @param to Recipient address that will receive the reminted ZWToken or the underlying token
/// @param id The token identifier. For fungible tokens without IDs (e.g., ERC-20), this MUST be set to `0`.
/// @param amount Amount of ZWToken burned from the provable burn address for reminting
/// @param withdrawUnderlying If true, withdraw the equivalent underlying token instead of reminting ZWToken
/// @param data Encapsulated remint data including commitment, nullifiers, proof, and relayer information
function remint(
address to,
uint256 id,
uint256 amount,
bool withdrawUnderlying,
RemintData calldata data
) external;
Key changes
IntroducedRemintData to align the remint pattern with deposit and withdraw, and avoid the “stack too deep” issue.
ReplacedrelayerFeewithrelayerData to support generic, more flexible relayer payloads.
AddedproverData to support richer prover-side data structures.
Replacednullifierwith an arraynullifiers enabling batch remint capabilities.
Additional updates
Renamed depositTo → deposit and withdrawTo → withdraw for a cleaner, more streamlined API, since the to parameter already captures the destination semantics.
Notably, we will soon open-source our implementation of ERC-8065, along with a PoC demonstrating our new ZWToken-unawareness workflow.