Skip to content

Conversation

grod220
Copy link
Member

@grod220 grod220 commented Jul 7, 2025

If the caller is creating a wrapped mint under the token-2022 program, the token wrap program will now add the ConfidentialTransfer extension by default.

@grod220 grod220 force-pushed the confidential-transfers branch 2 times, most recently from 07eb41b to 67ee807 Compare July 7, 2025 11:00
@grod220 grod220 requested review from joncinque and buffalojoec July 7, 2025 11:24
Copy link

@buffalojoec buffalojoec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the motivation here?

@grod220 grod220 force-pushed the confidential-transfers branch 2 times, most recently from 977cd17 to 33b418b Compare July 8, 2025 06:47
@grod220
Copy link
Member Author

grod220 commented Jul 8, 2025

What's the motivation here?

A follow up after #141. Arcium reached out for getting confidential transfer support on the wrapped mints. This had also been something brought up by the foundation in the past. After discussing with a few folks there, they felt it was something worthwhile to include by default. It essentially makes privacy a first-class citizen in the program as it would have out-of-the-box support. So in general, this is an effort to further promote this feature and its use in the ecosystem.

@buffalojoec
Copy link

Does it make sense to be opt-in or opt-out, rather than automatic? I'm sure there are some teams who probably really don't want to enable confidentiality.

@grod220
Copy link
Member Author

grod220 commented Jul 8, 2025

Does it make sense to be opt-in or opt-out, rather than automatic? I'm sure there are some teams who probably really don't want to enable confidentiality.

A few things come to mind:

  • The current design of the program with the wrapped mint PDA derivation does not accommodate varying extension configs. Having multiple different types of wrapped versions may add a burdensome complexity in trying to figure out which one is available and fragment liquidity.
  • This enables the option to use confidential transfers, but doesn't force its use. Users will be able to use their transparent balance all the same.
  • It is indeed a opinionated design though. Shipping it by default essentially says privacy should be the baseline. The escape hatch would be a fork.

Copy link
Contributor

@joncinque joncinque left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great to me!

Copy link

@buffalojoec buffalojoec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • This enables the option to use confidential transfers, but doesn't force its use. Users will be able to use their transparent balance all the same.
  • It is indeed a opinionated design though. Shipping it by default essentially says privacy should be the baseline. The escape hatch would be a fork.

It doesn't force its use but there's nothing you can do to stop its use. That's my point.

If I'm a protocol that cannot allow confidential transfers, I am barred from using the token wrap protocol because of this change. I would not make this automatic without an opt-out feature.

@joncinque
Copy link
Contributor

If I'm a protocol that cannot allow confidential transfers, I am barred from using the token wrap protocol because of this change.

What does this mean exactly? If a protocol cannot allow confidential transfers, the protocol can apply this policy on its own token accounts, by not enabling confidential transfers. But it shouldn't care about how other people use the token. Do you have any examples where this would be a problem?

I would not make this automatic without an opt-out feature.

If there's an opt-out, then anyone can grief the protocol by just creating all of the mints with or without the extension.

@grod220
Copy link
Member Author

grod220 commented Jul 10, 2025

Varying extension configurations for the wrapped mint is not something that we can reasonably allow for in the program. There are too many combinations and differing initialization params---which would prevent a sane PDA derivation scheme. A different wrapped mint config requires a fork.

So that essentially leaves us to choose an opinionated default. The motivation to include confidential transfer extension is to 1) serve requested usecases of folks wanting to use this program and 2) generally promote privacy as a normalized-standard.

@buffalojoec
Copy link

buffalojoec commented Jul 11, 2025

What does this mean exactly? If a protocol cannot allow confidential transfers, the protocol can apply this policy on its own token accounts, by not enabling confidential transfers. But it shouldn't care about how other people use the token. Do you have any examples where this would be a problem?

How about I'm an organization that issues United Arab Emirates Dirham stablecoins, and the government has strict requirements about transparency. Imagine they outright ban confidential token transfers altogether. If the mint supports confidential transfers, that means anyone can use that feature if they create a token account to do so.

If there's an opt-out, then anyone can grief the protocol by just creating all of the mints with or without the extension.

Wouldn't you also consider it griefing if I wrapped your mint - which does not allow confidential transfer - and could suddenly transfer it confidentially? I could just build an entire confidential transfer protocol that allows people to wrap their Dirham stables and transfer them confidentially.

(The irony is not lost on me that most of us would applaud such a protocol, however I find it hard to believe Anza wants to be responsible for enabling this in their program. Someone can easily fork and do this themselves, if they are okay with the risks involved)

Varying extension configurations for the wrapped mint is not something that we can reasonably allow for in the program. There are too many combinations and differing initialization params---which would prevent a sane PDA derivation scheme. A different wrapped mint config requires a fork.

That's true, and I would say if you wish to enable confidential transfers on a mint that does not currently have that extension, then by this definition (which applies to all other extensions) you should fork.

So that essentially leaves us to choose an opinionated default. The motivation to include confidential transfer extension is to 1) serve requested usecases of folks wanting to use this program and 2) generally promote privacy as a normalized-standard.

I don't believe this is our call to make if the original mint has not included this extension. We are essentially saying you cannot wrap tokens without enabling confidentiality, which is over-stepping. This program should only include ConfidentialTransfer if it already exists on the unwrapped mint.

@joncinque
Copy link
Contributor

This has come up as an issue in the past, especially around transfer fees. With this program as is, someone can just wrap a token that has transfer fees, and avoid paying them.

If an issuer doesn't like a particular version of a wrapped token, then they can just freeze the escrow holding all the tokens.

Either way, we should get more opinions on this before moving forward.

@cryptopapi997
Copy link

cryptopapi997 commented Jul 14, 2025

Giving my two cents here since we were one of the teams that initially asked for this:

If each time someone wants to wrap an existing token confidentially they need to fork this program this creates a huge mess with 100s if not 1000s of basically the same program floating around, some of which will inevitably include some kind of attack on unsuspecting people wrapping their token. If we assume this consolidates in one standardized forked wrap program that everyone uses at some point, it makes a lot of sense for this program to fall under the Anza parasol as a) this is a low-level primitive centered around SPL-token and Token2022, both of which are for the most part maintained by Anza atm (similar situation as wrapped SOL in my mind) and b) there already exists the token-wrap program whose purpose is to wrap tokens anyhow.

Re the concerns around wrapping tokens people don't want to be confidential, I see it the same way Jon said - in fact, an issuer could even create the escrow with this program & then immediately freeze it if they want to be extra clear that they don't want this for their token.

@grod220 grod220 force-pushed the confidential-transfers branch 4 times, most recently from 9965623 to 19cfdf9 Compare July 25, 2025 11:32
@grod220
Copy link
Member Author

grod220 commented Jul 25, 2025

Post discussions on token-wrap direction, updated this PR to make use of the new MintCustomizer. Metadata extension will be followed up with next.

@grod220 grod220 requested review from buffalojoec and joncinque July 25, 2025 12:25
@buffalojoec buffalojoec dismissed their stale review July 28, 2025 01:05

Unblocking based on discussion

Copy link
Contributor

@joncinque joncinque left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some tiny nits, the rest looks great!

Comment on lines 121 to 127
// For token-2022, confidential transfers extension added by default
let extensions = if args.wrapped_token_program == spl_token_2022::id() {
vec![ExtensionType::ConfidentialTransferMint]
} else {
vec![]
};
let mint_size = ExtensionType::try_calculate_account_len::<Mint>(&extensions)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: how about calling the mint customizer directly?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The challenge is that the customizer trait requires access to accounts. It's sort of designed with only the program use-case in mind.

fn get_token_2022_mint_space(
  unwrapped_mint_account: &AccountInfo,
  all_accounts: &[AccountInfo],
) 

It assumes that account arguments could potentially be used to calculate space. For the other methods, accounts are definitely needed. But perhaps it's not really necessary for calculating space? What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah right my bad, I forgot because none of the implementations were using the accounts 😅

Do you know of use-cases where the accounts would be needed? The only possibility I could think of was metadata, but that's a variable-length extension, and all variable-length extensions are initialized after the mint is initialized, so we wouldn't need it here to calculate the space

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think it's reasonable to update the interface and we can later add to it as more is actually needed. We can probably change all methods to associated functions too (versus methods) as we aren't using any struct state.

@grod220 grod220 force-pushed the confidential-transfers branch from 19cfdf9 to 33f2358 Compare July 29, 2025 19:12
Copy link
Contributor

@joncinque joncinque left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit: !

@grod220 grod220 merged commit 970df70 into main Jul 30, 2025
10 checks passed
@grod220 grod220 deleted the confidential-transfers branch July 30, 2025 06:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants