ERC‑8065: Zero Knowledge Token Wrapper

Thanks for your interest in ERC-8605 — I’m also excited about the recent surge of related work, including this thread (which is quite similar to what you’re doing): zERC20 : Cross-Chain Private ERC-20 Based on ZK Proof-of-Burn

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.

I think changing uint256 relayerFee to bytes calldata relayerData would make it more general and able to support various forms of fees.

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.

Happy to expand further if useful.

2 Likes

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.

Additionally, should we add a bytes calldata minterData to correspond to bytes calldata relayerData, so that more scenarios can be supported?

But at the moment, I still can’t think of any scenarios that would require minterData.

    function remint(
        bytes calldata proof,
        bytes32 commitment,
        bytes32 nullifier,
        address to,
        uint256 id,
        uint256 amount,
        bool withdrawUnderlying,
        bytes calldata relayerData
    ) external;

I think we can use bytes32[] nullifiers instead of bytes32 nullifier to support batch reminting.

2 Likes

Great idea — it would be even better if the multiple nullifiers provided do not leak privacy to each other.

ERC-8065 Update [2025.12.2] — Major Improvements to the remint Interface

We’ve updated the remint interface to make it more extensible, consistent, and aligned with future use cases.

Previous interface:

function remint(
    bytes calldata proof,
    bytes32 commitment,
    bytes32 nullifier,
    address to,
    uint256 id,
    uint256 amount,
    bool withdrawUnderlying,
    uint256 relayerFee
) external;

New interface:

/// @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

  • Introduced RemintData to align the remint pattern with deposit and withdraw, and avoid the “stack too deep” issue.
  • Replaced relayerFee with relayerData to support generic, more flexible relayer payloads.
  • Added proverData to support richer prover-side data structures.
  • Replaced nullifier with an array nullifiers 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.

2 Likes

ERC-8065 Update [2025.12.8]:

1 Like

Thanks for considering my proposal for improving ERC-8065! Let me know if you have any questions regarding my stack!

1 Like

What about adding parameter data to deposit and withdraw to support extensible innovations built on top of 8065?

2 Likes

Good idea. This means ERC-8065 can support extensions such as private messaging. Looking forward to the follow-up work of @ZyraV21

1 Like

Definetely. I’ll open a new thread as a proposal for start discussing about a potential ‘private chat’ and "stealth adresses’ extensions … Your perspective and help will be really appreciated onto this new proposal @doublespending

One angle I haven’t seen discussed yet is the effect of burn-and-remint on temporal reputation.

If asset history can be reset at will, how should downstream systems reason about address-level trust, governance participation, or risk scoring?

Burn-and-remint mainly obscures history for parties other than the operator, while the operator themselves remains fully aware.

With user consent, history can still be followed relatively easily: users can prove ownership of a given address—whether a burn address or a regular address—via signatures or zero-knowledge proofs. Within the scope explicitly authorized by the user, tracking historical continuity is therefore quite feasible.

ERC-8065 Update [2025.12.22]


Follow us

How large is the anonymous collection of ERC8065, and how does it compare to Tornado Cash and Railgun?

How large is the anonymous collection of ERC8065, and how does it compare to Tornado Cash and Railgun?

The ZWToken approach should, in theory, have a larger anonymity set than a privacy dApp. Due to ZWToken’s pluggable privacy design, it can be used like a regular token and therefore supports many non-privacy use cases. In simple terms, ZWToken’s anonymity set consists of both regular token usage and privacy-preserving token usage, which is larger than that of a privacy dApp that only supports privacy-focused token usage.

2 Likes
function getFeeConfig() external view returns (uint256 depositFee, uint256 remintFee, uint256 withdrawFee, uint256 feeDenominator);

I think there are some issues with defining fee formats and structures in the ERC, because fee models are not necessarily fully covered by the three values depositFee, remintFee, and withdrawFee. This is especially true when considering dynamic fees, or fees that are not proportional to token amounts. In addition, NFTs do not seem to be divisible, which makes them difficult to use for paying fees.

I think there are some issues with defining fee formats and structures in the ERC, because fee models are not necessarily fully covered by the three values depositFee, remintFee, and withdrawFee. This is especially true when considering dynamic fees, or fees that are not proportional to token amounts. In addition, NFTs do not seem to be divisible, which makes them difficult to use for paying fees.

That’s a really good suggestion. I agree that putting fee definitions directly into the ERC isn’t a great design choice, since fees can take many different forms—dynamic fees, membership-based fees, and so on—and they’re not necessarily a fixed percentage. Also, for tokens like NFTs that aren’t divisible, it’s simply not feasible to charge fees at the token level.

So I’m going to update the ERC and remove fees from it.

Originally, fees were added mainly so users could know how many tokens they would actually get at each stage—deposit, withdraw, and remint. With fees removed, we can still support this by adding optional preview functions for deposit, withdraw, and remint, similar to what existing vault ERCs already do.

1 Like