Skip to content

Commit f521153

Browse files
committed
refactor: relax ata decompress signer check, feat: add ata decompress idempotent
1 parent 2809be4 commit f521153

16 files changed

Lines changed: 953 additions & 31 deletions

File tree

js/compressed-token/src/v3/layout/layout-transfer2.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export const EXTENSION_DISCRIMINANT_COMPRESSIBLE = 32;
3131
export const COMPRESSION_MODE_COMPRESS = 0;
3232
export const COMPRESSION_MODE_DECOMPRESS = 1;
3333
export const COMPRESSION_MODE_COMPRESS_AND_CLOSE = 2;
34+
export const COMPRESSION_MODE_DECOMPRESS_IDEMPOTENT = 3;
3435

3536
/**
3637
* Compression struct for Transfer2 instruction

program-libs/token-interface/src/error.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,12 @@ pub enum TokenError {
206206

207207
#[error("ATA derivation failed or mismatched for is_ata compressed token")]
208208
InvalidAtaDerivation,
209+
210+
#[error("DecompressIdempotent requires exactly 1 input and 1 compression")]
211+
IdempotentDecompressRequiresSingleInput,
212+
213+
#[error("DecompressIdempotent is only supported for ATA accounts (is_ata must be true)")]
214+
IdempotentDecompressRequiresAta,
209215
}
210216

211217
impl From<TokenError> for u32 {
@@ -277,6 +283,8 @@ impl From<TokenError> for u32 {
277283
TokenError::DecompressAmountMismatch => 18064,
278284
TokenError::CompressionIndexOutOfBounds => 18065,
279285
TokenError::InvalidAtaDerivation => 18066,
286+
TokenError::IdempotentDecompressRequiresSingleInput => 18067,
287+
TokenError::IdempotentDecompressRequiresAta => 18068,
280288
TokenError::HasherError(e) => u32::from(e),
281289
TokenError::ZeroCopyError(e) => u32::from(e),
282290
TokenError::CompressedAccountError(e) => u32::from(e),

program-libs/token-interface/src/instructions/transfer2/compression.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ pub enum CompressionMode {
1616
/// Signer must be rent authority, token account must be compressible
1717
/// Not implemented for spl token accounts.
1818
CompressAndClose,
19+
/// Permissionless ATA decompress with single-input constraint.
20+
/// Requires CompressedOnly extension with is_ata=true.
21+
/// On-chain behavior is identical to Decompress.
22+
DecompressIdempotent,
1923
}
2024

2125
impl ZCompressionMode {
@@ -24,7 +28,14 @@ impl ZCompressionMode {
2428
}
2529

2630
pub fn is_decompress(&self) -> bool {
27-
matches!(self, ZCompressionMode::Decompress)
31+
matches!(
32+
self,
33+
ZCompressionMode::Decompress | ZCompressionMode::DecompressIdempotent
34+
)
35+
}
36+
37+
pub fn is_decompress_idempotent(&self) -> bool {
38+
matches!(self, ZCompressionMode::DecompressIdempotent)
2839
}
2940

3041
pub fn is_compress_and_close(&self) -> bool {
@@ -35,6 +46,7 @@ impl ZCompressionMode {
3546
pub const COMPRESS: u8 = 0u8;
3647
pub const DECOMPRESS: u8 = 1u8;
3748
pub const COMPRESS_AND_CLOSE: u8 = 2u8;
49+
pub const DECOMPRESS_IDEMPOTENT: u8 = 3u8;
3850

3951
impl<'a> ZeroCopyAtMut<'a> for CompressionMode {
4052
type ZeroCopyAtMut = Ref<&'a mut [u8], u8>;
@@ -204,6 +216,20 @@ impl Compression {
204216
decimals: 0,
205217
}
206218
}
219+
220+
pub fn decompress_idempotent(amount: u64, mint: u8, recipient: u8) -> Self {
221+
Compression {
222+
amount,
223+
mode: CompressionMode::DecompressIdempotent,
224+
mint,
225+
source_or_recipient: recipient,
226+
authority: 0,
227+
pool_account_index: 0,
228+
pool_index: 0,
229+
bump: 0,
230+
decimals: 0,
231+
}
232+
}
207233
}
208234

209235
impl ZCompressionMut<'_> {
@@ -212,6 +238,7 @@ impl ZCompressionMut<'_> {
212238
COMPRESS => Ok(CompressionMode::Compress),
213239
DECOMPRESS => Ok(CompressionMode::Decompress),
214240
COMPRESS_AND_CLOSE => Ok(CompressionMode::CompressAndClose),
241+
DECOMPRESS_IDEMPOTENT => Ok(CompressionMode::DecompressIdempotent),
215242
_ => Err(TokenError::InvalidCompressionMode),
216243
}
217244
}
@@ -226,7 +253,7 @@ impl ZCompression<'_> {
226253
.checked_add((*self.amount).into())
227254
.ok_or(TokenError::ArithmeticOverflow)
228255
}
229-
ZCompressionMode::Decompress => {
256+
ZCompressionMode::Decompress | ZCompressionMode::DecompressIdempotent => {
230257
// Decompress: subtract from balance (tokens are being removed from spl token pool)
231258
current_balance
232259
.checked_sub((*self.amount).into())

0 commit comments

Comments
 (0)