From 6c25b05ac1991a0055765241bfa6e9b1e103d54c Mon Sep 17 00:00:00 2001 From: febo Date: Wed, 5 Feb 2025 23:55:27 +0000 Subject: [PATCH 01/16] Update workspace --- Cargo.lock | 293 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index f30c2e0f..6de43135 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2680,6 +2680,7 @@ checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc" dependencies = [ "cc", "libc", + "openssl-src", "pkg-config", "vcpkg", ] @@ -5460,6 +5461,173 @@ dependencies = [ "solana-sysvar-id", ] +[[package]] +name = "solana-rpc-client" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7b40d68b77b47a7786965eca51207dd19cb68bb518da7476e84cc4f87f5c334" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bincode", + "bs58", + "indicatif", + "log", + "reqwest", + "reqwest-middleware", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder-client-types", + "solana-rpc-client-api", + "solana-sdk", + "solana-transaction-status-client-types", + "solana-version", + "solana-vote-program", + "tokio", +] + +[[package]] +name = "solana-rpc-client-api" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4520467a0bb012c7ecf121eaae0182d4c3c0647844c6bbcbeea87997a9cdc97e" +dependencies = [ + "anyhow", + "base64 0.22.1", + "bs58", + "jsonrpc-core", + "reqwest", + "reqwest-middleware", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder-client-types", + "solana-inline-spl", + "solana-sdk", + "solana-transaction-status-client-types", + "solana-version", + "thiserror 1.0.69", +] + +[[package]] +name = "solana-rpc-client-nonce-utils" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1396307c7e3a72ed8074cb1c31f7f6613d3e71f0f3414911ccbaeea29690158d" +dependencies = [ + "solana-rpc-client", + "solana-sdk", + "thiserror 1.0.69", +] + +[[package]] +name = "solana-runtime" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cebb07bfc23c41c5f63dd00f62a377e9d30903e551ddc570aced74ab729c340b" +dependencies = [ + "ahash", + "aquamarine", + "arrayref", + "base64 0.22.1", + "bincode", + "blake3", + "bv", + "bytemuck", + "byteorder", + "bzip2", + "crossbeam-channel", + "dashmap", + "dir-diff", + "flate2", + "fnv", + "im", + "index_list", + "itertools 0.12.1", + "lazy_static", + "libc", + "log", + "lz4", + "memmap2", + "mockall", + "modular-bitfield", + "num-derive", + "num-traits", + "num_cpus", + "num_enum", + "percentage", + "qualifier_attr", + "rand 0.8.5", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "serde_with", + "solana-accounts-db", + "solana-address-lookup-table-program", + "solana-bpf-loader-program", + "solana-bucket-map", + "solana-compute-budget", + "solana-compute-budget-program", + "solana-config-program", + "solana-cost-model", + "solana-feature-set", + "solana-fee", + "solana-inline-spl", + "solana-lattice-hash", + "solana-loader-v4-program", + "solana-measure", + "solana-metrics", + "solana-perf", + "solana-program", + "solana-program-runtime", + "solana-rayon-threadlimit", + "solana-runtime-transaction", + "solana-sdk", + "solana-stake-program", + "solana-svm", + "solana-svm-rent-collector", + "solana-svm-transaction", + "solana-system-program", + "solana-timings", + "solana-transaction-status", + "solana-version", + "solana-vote", + "solana-vote-program", + "solana-zk-elgamal-proof-program", + "solana-zk-sdk", + "solana-zk-token-proof-program", + "solana-zk-token-sdk", + "static_assertions", + "strum", + "strum_macros", + "symlink", + "tar", + "tempfile", + "thiserror 1.0.69", + "zstd", +] + +[[package]] +name = "solana-runtime-transaction" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "242b34f49b0c31f8f10681e4f0c15f4e5d49da7da89ce7f524e0877d5ce8e9cc" +dependencies = [ + "agave-transaction-view", + "log", + "solana-builtins-default-costs", + "solana-compute-budget", + "solana-pubkey", + "solana-sdk", + "solana-svm-transaction", + "thiserror 1.0.69", +] + [[package]] name = "solana-rent-collector" version = "2.2.1" @@ -6022,6 +6190,109 @@ dependencies = [ "solana-pubkey", ] +[[package]] +name = "solana-stake-program" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7803aae3aa3c4b344bd6eb2107dd7a897f15b9614af4d5c6dbaf9026bc39a1fe" +dependencies = [ + "bincode", + "log", + "solana-config-program", + "solana-feature-set", + "solana-log-collector", + "solana-program-runtime", + "solana-sdk", + "solana-type-overrides", + "solana-vote-program", +] + +[[package]] +name = "solana-streamer" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85090db4563b271711d44275a20d1becb4a92e2fdeb41f5234b45df0321e807d" +dependencies = [ + "async-channel", + "bytes", + "crossbeam-channel", + "dashmap", + "futures", + "futures-util", + "governor", + "histogram", + "indexmap", + "itertools 0.12.1", + "libc", + "log", + "nix", + "pem", + "percentage", + "quinn", + "quinn-proto", + "rand 0.8.5", + "rustls 0.23.22", + "smallvec", + "socket2", + "solana-measure", + "solana-metrics", + "solana-perf", + "solana-sdk", + "solana-transaction-metrics-tracker", + "thiserror 1.0.69", + "tokio", + "tokio-util 0.7.13", + "x509-parser", +] + +[[package]] +name = "solana-svm" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee008a28c6c24be2ae5d0dad2df607201af975ec3cb4ea4f26d0dd1c6d05aa7a" +dependencies = [ + "itertools 0.12.1", + "log", + "percentage", + "serde", + "serde_derive", + "solana-bpf-loader-program", + "solana-compute-budget", + "solana-feature-set", + "solana-fee", + "solana-loader-v4-program", + "solana-log-collector", + "solana-measure", + "solana-program-runtime", + "solana-runtime-transaction", + "solana-sdk", + "solana-svm-rent-collector", + "solana-svm-transaction", + "solana-system-program", + "solana-timings", + "solana-type-overrides", + "solana-vote", + "thiserror 1.0.69", +] + +[[package]] +name = "solana-svm-rent-collector" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9c1360c7382ec61503aab743068c443fd235e1087adb71216de6f03612062a5" +dependencies = [ + "solana-sdk", +] + +[[package]] +name = "solana-svm-transaction" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cce3a10755daa103d6c5bcb119515e8a44db6c69d2e37b54704128e11c5356" +dependencies = [ + "solana-sdk", +] + [[package]] name = "solana-stake-interface" version = "1.2.1" @@ -7160,6 +7431,28 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "token-interface" +version = "0.0.0" +dependencies = [ + "pinocchio", + "pinocchio-pubkey", +] + +[[package]] +name = "token-program" +version = "0.0.0" +dependencies = [ + "assert_matches", + "pinocchio", + "pinocchio-log", + "solana-program-test", + "solana-sdk", + "spl-token 4.0.2", + "test-case", + "token-interface", +] + [[package]] name = "tokio" version = "1.43.0" From 8f17cd993a25f7dc5ea0478b5e2bc682c8390682 Mon Sep 17 00:00:00 2001 From: febo Date: Thu, 13 Feb 2025 23:21:23 +0000 Subject: [PATCH 02/16] Rename interface crate --- Cargo.lock | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6de43135..dc1457fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7431,28 +7431,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "token-interface" -version = "0.0.0" -dependencies = [ - "pinocchio", - "pinocchio-pubkey", -] - -[[package]] -name = "token-program" -version = "0.0.0" -dependencies = [ - "assert_matches", - "pinocchio", - "pinocchio-log", - "solana-program-test", - "solana-sdk", - "spl-token 4.0.2", - "test-case", - "token-interface", -] - [[package]] name = "tokio" version = "1.43.0" From d9be865b863a78fdc25f43137bfee46dfe6fdfcf Mon Sep 17 00:00:00 2001 From: febo Date: Thu, 6 Feb 2025 00:46:38 +0000 Subject: [PATCH 03/16] Fix spelling --- Cargo.lock | 271 ----------------------------------------------------- 1 file changed, 271 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc1457fd..f30c2e0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2680,7 +2680,6 @@ checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc" dependencies = [ "cc", "libc", - "openssl-src", "pkg-config", "vcpkg", ] @@ -5461,173 +5460,6 @@ dependencies = [ "solana-sysvar-id", ] -[[package]] -name = "solana-rpc-client" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7b40d68b77b47a7786965eca51207dd19cb68bb518da7476e84cc4f87f5c334" -dependencies = [ - "async-trait", - "base64 0.22.1", - "bincode", - "bs58", - "indicatif", - "log", - "reqwest", - "reqwest-middleware", - "semver", - "serde", - "serde_derive", - "serde_json", - "solana-account-decoder-client-types", - "solana-rpc-client-api", - "solana-sdk", - "solana-transaction-status-client-types", - "solana-version", - "solana-vote-program", - "tokio", -] - -[[package]] -name = "solana-rpc-client-api" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4520467a0bb012c7ecf121eaae0182d4c3c0647844c6bbcbeea87997a9cdc97e" -dependencies = [ - "anyhow", - "base64 0.22.1", - "bs58", - "jsonrpc-core", - "reqwest", - "reqwest-middleware", - "semver", - "serde", - "serde_derive", - "serde_json", - "solana-account-decoder-client-types", - "solana-inline-spl", - "solana-sdk", - "solana-transaction-status-client-types", - "solana-version", - "thiserror 1.0.69", -] - -[[package]] -name = "solana-rpc-client-nonce-utils" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1396307c7e3a72ed8074cb1c31f7f6613d3e71f0f3414911ccbaeea29690158d" -dependencies = [ - "solana-rpc-client", - "solana-sdk", - "thiserror 1.0.69", -] - -[[package]] -name = "solana-runtime" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cebb07bfc23c41c5f63dd00f62a377e9d30903e551ddc570aced74ab729c340b" -dependencies = [ - "ahash", - "aquamarine", - "arrayref", - "base64 0.22.1", - "bincode", - "blake3", - "bv", - "bytemuck", - "byteorder", - "bzip2", - "crossbeam-channel", - "dashmap", - "dir-diff", - "flate2", - "fnv", - "im", - "index_list", - "itertools 0.12.1", - "lazy_static", - "libc", - "log", - "lz4", - "memmap2", - "mockall", - "modular-bitfield", - "num-derive", - "num-traits", - "num_cpus", - "num_enum", - "percentage", - "qualifier_attr", - "rand 0.8.5", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "serde_with", - "solana-accounts-db", - "solana-address-lookup-table-program", - "solana-bpf-loader-program", - "solana-bucket-map", - "solana-compute-budget", - "solana-compute-budget-program", - "solana-config-program", - "solana-cost-model", - "solana-feature-set", - "solana-fee", - "solana-inline-spl", - "solana-lattice-hash", - "solana-loader-v4-program", - "solana-measure", - "solana-metrics", - "solana-perf", - "solana-program", - "solana-program-runtime", - "solana-rayon-threadlimit", - "solana-runtime-transaction", - "solana-sdk", - "solana-stake-program", - "solana-svm", - "solana-svm-rent-collector", - "solana-svm-transaction", - "solana-system-program", - "solana-timings", - "solana-transaction-status", - "solana-version", - "solana-vote", - "solana-vote-program", - "solana-zk-elgamal-proof-program", - "solana-zk-sdk", - "solana-zk-token-proof-program", - "solana-zk-token-sdk", - "static_assertions", - "strum", - "strum_macros", - "symlink", - "tar", - "tempfile", - "thiserror 1.0.69", - "zstd", -] - -[[package]] -name = "solana-runtime-transaction" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "242b34f49b0c31f8f10681e4f0c15f4e5d49da7da89ce7f524e0877d5ce8e9cc" -dependencies = [ - "agave-transaction-view", - "log", - "solana-builtins-default-costs", - "solana-compute-budget", - "solana-pubkey", - "solana-sdk", - "solana-svm-transaction", - "thiserror 1.0.69", -] - [[package]] name = "solana-rent-collector" version = "2.2.1" @@ -6190,109 +6022,6 @@ dependencies = [ "solana-pubkey", ] -[[package]] -name = "solana-stake-program" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803aae3aa3c4b344bd6eb2107dd7a897f15b9614af4d5c6dbaf9026bc39a1fe" -dependencies = [ - "bincode", - "log", - "solana-config-program", - "solana-feature-set", - "solana-log-collector", - "solana-program-runtime", - "solana-sdk", - "solana-type-overrides", - "solana-vote-program", -] - -[[package]] -name = "solana-streamer" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85090db4563b271711d44275a20d1becb4a92e2fdeb41f5234b45df0321e807d" -dependencies = [ - "async-channel", - "bytes", - "crossbeam-channel", - "dashmap", - "futures", - "futures-util", - "governor", - "histogram", - "indexmap", - "itertools 0.12.1", - "libc", - "log", - "nix", - "pem", - "percentage", - "quinn", - "quinn-proto", - "rand 0.8.5", - "rustls 0.23.22", - "smallvec", - "socket2", - "solana-measure", - "solana-metrics", - "solana-perf", - "solana-sdk", - "solana-transaction-metrics-tracker", - "thiserror 1.0.69", - "tokio", - "tokio-util 0.7.13", - "x509-parser", -] - -[[package]] -name = "solana-svm" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee008a28c6c24be2ae5d0dad2df607201af975ec3cb4ea4f26d0dd1c6d05aa7a" -dependencies = [ - "itertools 0.12.1", - "log", - "percentage", - "serde", - "serde_derive", - "solana-bpf-loader-program", - "solana-compute-budget", - "solana-feature-set", - "solana-fee", - "solana-loader-v4-program", - "solana-log-collector", - "solana-measure", - "solana-program-runtime", - "solana-runtime-transaction", - "solana-sdk", - "solana-svm-rent-collector", - "solana-svm-transaction", - "solana-system-program", - "solana-timings", - "solana-type-overrides", - "solana-vote", - "thiserror 1.0.69", -] - -[[package]] -name = "solana-svm-rent-collector" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9c1360c7382ec61503aab743068c443fd235e1087adb71216de6f03612062a5" -dependencies = [ - "solana-sdk", -] - -[[package]] -name = "solana-svm-transaction" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cce3a10755daa103d6c5bcb119515e8a44db6c69d2e37b54704128e11c5356" -dependencies = [ - "solana-sdk", -] - [[package]] name = "solana-stake-interface" version = "1.2.1" From 3456baad0387e40824220cb77cb5506c26d6adb2 Mon Sep 17 00:00:00 2001 From: febo Date: Wed, 5 Mar 2025 14:14:58 +0000 Subject: [PATCH 04/16] [wip]: Fix review comments --- p-token/src/processor/set_authority.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/p-token/src/processor/set_authority.rs b/p-token/src/processor/set_authority.rs index b621eeba..e4b8f43a 100644 --- a/p-token/src/processor/set_authority.rs +++ b/p-token/src/processor/set_authority.rs @@ -45,11 +45,11 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) return Err(TokenError::AccountFrozen.into()); } - match authority_type { + match args.authority_type { AuthorityType::AccountOwner => { validate_owner(&account.owner, authority_info, remaining)?; - if let Some(authority) = new_authority { + if let Some(authority) = args.new_authority { account.owner = *authority; } else { return Err(TokenError::InvalidInstruction.into()); @@ -66,7 +66,7 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) let authority = account.close_authority().unwrap_or(&account.owner); validate_owner(authority, authority_info, remaining)?; - if let Some(authority) = new_authority { + if let Some(authority) = args.new_authority { account.set_close_authority(authority); } else { account.clear_close_authority(); @@ -81,7 +81,7 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) // `load_mut` validates that the mint is initialized. let mint = unsafe { load_mut::(account_info.borrow_mut_data_unchecked())? }; - match authority_type { + match args.authority_type { AuthorityType::MintTokens => { // Once a mint's supply is fixed, it cannot be undone by setting a new // mint_authority. @@ -89,7 +89,7 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) validate_owner(mint_authority, authority_info, remaining)?; - if let Some(authority) = new_authority { + if let Some(authority) = args.new_authority { mint.set_mint_authority(authority); } else { mint.clear_mint_authority(); @@ -104,7 +104,7 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) validate_owner(freeze_authority, authority_info, remaining)?; - if let Some(authority) = new_authority { + if let Some(authority) = args.new_authority { mint.set_freeze_authority(authority); } else { mint.clear_freeze_authority(); From 863d22dd7a5e49d85a94902c89a730c972349a18 Mon Sep 17 00:00:00 2001 From: febo Date: Thu, 6 Mar 2025 19:31:56 +0000 Subject: [PATCH 05/16] A few more fixes --- p-token/src/processor/set_authority.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/p-token/src/processor/set_authority.rs b/p-token/src/processor/set_authority.rs index e4b8f43a..c3c8568f 100644 --- a/p-token/src/processor/set_authority.rs +++ b/p-token/src/processor/set_authority.rs @@ -45,11 +45,11 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) return Err(TokenError::AccountFrozen.into()); } - match args.authority_type { + match args.authority_type()? { AuthorityType::AccountOwner => { validate_owner(&account.owner, authority_info, remaining)?; - if let Some(authority) = args.new_authority { + if let Some(authority) = args.new_authority() { account.owner = *authority; } else { return Err(TokenError::InvalidInstruction.into()); @@ -66,7 +66,7 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) let authority = account.close_authority().unwrap_or(&account.owner); validate_owner(authority, authority_info, remaining)?; - if let Some(authority) = args.new_authority { + if let Some(authority) = args.new_authority() { account.set_close_authority(authority); } else { account.clear_close_authority(); @@ -81,7 +81,7 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) // `load_mut` validates that the mint is initialized. let mint = unsafe { load_mut::(account_info.borrow_mut_data_unchecked())? }; - match args.authority_type { + match args.authority_type()? { AuthorityType::MintTokens => { // Once a mint's supply is fixed, it cannot be undone by setting a new // mint_authority. @@ -89,7 +89,7 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) validate_owner(mint_authority, authority_info, remaining)?; - if let Some(authority) = args.new_authority { + if let Some(authority) = args.new_authority() { mint.set_mint_authority(authority); } else { mint.clear_mint_authority(); @@ -104,7 +104,7 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) validate_owner(freeze_authority, authority_info, remaining)?; - if let Some(authority) = args.new_authority { + if let Some(authority) = args.new_authority() { mint.set_freeze_authority(authority); } else { mint.clear_freeze_authority(); From 4e9fe435cf2cb51489353e131396ba54434c038c Mon Sep 17 00:00:00 2001 From: febo Date: Mon, 10 Mar 2025 16:24:58 +0000 Subject: [PATCH 06/16] Fix merge --- p-token/src/processor/set_authority.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/p-token/src/processor/set_authority.rs b/p-token/src/processor/set_authority.rs index c3c8568f..b621eeba 100644 --- a/p-token/src/processor/set_authority.rs +++ b/p-token/src/processor/set_authority.rs @@ -45,11 +45,11 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) return Err(TokenError::AccountFrozen.into()); } - match args.authority_type()? { + match authority_type { AuthorityType::AccountOwner => { validate_owner(&account.owner, authority_info, remaining)?; - if let Some(authority) = args.new_authority() { + if let Some(authority) = new_authority { account.owner = *authority; } else { return Err(TokenError::InvalidInstruction.into()); @@ -66,7 +66,7 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) let authority = account.close_authority().unwrap_or(&account.owner); validate_owner(authority, authority_info, remaining)?; - if let Some(authority) = args.new_authority() { + if let Some(authority) = new_authority { account.set_close_authority(authority); } else { account.clear_close_authority(); @@ -81,7 +81,7 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) // `load_mut` validates that the mint is initialized. let mint = unsafe { load_mut::(account_info.borrow_mut_data_unchecked())? }; - match args.authority_type()? { + match authority_type { AuthorityType::MintTokens => { // Once a mint's supply is fixed, it cannot be undone by setting a new // mint_authority. @@ -89,7 +89,7 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) validate_owner(mint_authority, authority_info, remaining)?; - if let Some(authority) = args.new_authority() { + if let Some(authority) = new_authority { mint.set_mint_authority(authority); } else { mint.clear_mint_authority(); @@ -104,7 +104,7 @@ pub fn process_set_authority(accounts: &[AccountInfo], instruction_data: &[u8]) validate_owner(freeze_authority, authority_info, remaining)?; - if let Some(authority) = args.new_authority() { + if let Some(authority) = new_authority { mint.set_freeze_authority(authority); } else { mint.clear_freeze_authority(); From 2b16d392cd3e8c293b0a83b176fe6d45eb63b88f Mon Sep 17 00:00:00 2001 From: febo Date: Wed, 5 Feb 2025 23:55:27 +0000 Subject: [PATCH 07/16] Update workspace --- Cargo.lock | 293 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index f30c2e0f..6de43135 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2680,6 +2680,7 @@ checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc" dependencies = [ "cc", "libc", + "openssl-src", "pkg-config", "vcpkg", ] @@ -5460,6 +5461,173 @@ dependencies = [ "solana-sysvar-id", ] +[[package]] +name = "solana-rpc-client" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7b40d68b77b47a7786965eca51207dd19cb68bb518da7476e84cc4f87f5c334" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bincode", + "bs58", + "indicatif", + "log", + "reqwest", + "reqwest-middleware", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder-client-types", + "solana-rpc-client-api", + "solana-sdk", + "solana-transaction-status-client-types", + "solana-version", + "solana-vote-program", + "tokio", +] + +[[package]] +name = "solana-rpc-client-api" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4520467a0bb012c7ecf121eaae0182d4c3c0647844c6bbcbeea87997a9cdc97e" +dependencies = [ + "anyhow", + "base64 0.22.1", + "bs58", + "jsonrpc-core", + "reqwest", + "reqwest-middleware", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder-client-types", + "solana-inline-spl", + "solana-sdk", + "solana-transaction-status-client-types", + "solana-version", + "thiserror 1.0.69", +] + +[[package]] +name = "solana-rpc-client-nonce-utils" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1396307c7e3a72ed8074cb1c31f7f6613d3e71f0f3414911ccbaeea29690158d" +dependencies = [ + "solana-rpc-client", + "solana-sdk", + "thiserror 1.0.69", +] + +[[package]] +name = "solana-runtime" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cebb07bfc23c41c5f63dd00f62a377e9d30903e551ddc570aced74ab729c340b" +dependencies = [ + "ahash", + "aquamarine", + "arrayref", + "base64 0.22.1", + "bincode", + "blake3", + "bv", + "bytemuck", + "byteorder", + "bzip2", + "crossbeam-channel", + "dashmap", + "dir-diff", + "flate2", + "fnv", + "im", + "index_list", + "itertools 0.12.1", + "lazy_static", + "libc", + "log", + "lz4", + "memmap2", + "mockall", + "modular-bitfield", + "num-derive", + "num-traits", + "num_cpus", + "num_enum", + "percentage", + "qualifier_attr", + "rand 0.8.5", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "serde_with", + "solana-accounts-db", + "solana-address-lookup-table-program", + "solana-bpf-loader-program", + "solana-bucket-map", + "solana-compute-budget", + "solana-compute-budget-program", + "solana-config-program", + "solana-cost-model", + "solana-feature-set", + "solana-fee", + "solana-inline-spl", + "solana-lattice-hash", + "solana-loader-v4-program", + "solana-measure", + "solana-metrics", + "solana-perf", + "solana-program", + "solana-program-runtime", + "solana-rayon-threadlimit", + "solana-runtime-transaction", + "solana-sdk", + "solana-stake-program", + "solana-svm", + "solana-svm-rent-collector", + "solana-svm-transaction", + "solana-system-program", + "solana-timings", + "solana-transaction-status", + "solana-version", + "solana-vote", + "solana-vote-program", + "solana-zk-elgamal-proof-program", + "solana-zk-sdk", + "solana-zk-token-proof-program", + "solana-zk-token-sdk", + "static_assertions", + "strum", + "strum_macros", + "symlink", + "tar", + "tempfile", + "thiserror 1.0.69", + "zstd", +] + +[[package]] +name = "solana-runtime-transaction" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "242b34f49b0c31f8f10681e4f0c15f4e5d49da7da89ce7f524e0877d5ce8e9cc" +dependencies = [ + "agave-transaction-view", + "log", + "solana-builtins-default-costs", + "solana-compute-budget", + "solana-pubkey", + "solana-sdk", + "solana-svm-transaction", + "thiserror 1.0.69", +] + [[package]] name = "solana-rent-collector" version = "2.2.1" @@ -6022,6 +6190,109 @@ dependencies = [ "solana-pubkey", ] +[[package]] +name = "solana-stake-program" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7803aae3aa3c4b344bd6eb2107dd7a897f15b9614af4d5c6dbaf9026bc39a1fe" +dependencies = [ + "bincode", + "log", + "solana-config-program", + "solana-feature-set", + "solana-log-collector", + "solana-program-runtime", + "solana-sdk", + "solana-type-overrides", + "solana-vote-program", +] + +[[package]] +name = "solana-streamer" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85090db4563b271711d44275a20d1becb4a92e2fdeb41f5234b45df0321e807d" +dependencies = [ + "async-channel", + "bytes", + "crossbeam-channel", + "dashmap", + "futures", + "futures-util", + "governor", + "histogram", + "indexmap", + "itertools 0.12.1", + "libc", + "log", + "nix", + "pem", + "percentage", + "quinn", + "quinn-proto", + "rand 0.8.5", + "rustls 0.23.22", + "smallvec", + "socket2", + "solana-measure", + "solana-metrics", + "solana-perf", + "solana-sdk", + "solana-transaction-metrics-tracker", + "thiserror 1.0.69", + "tokio", + "tokio-util 0.7.13", + "x509-parser", +] + +[[package]] +name = "solana-svm" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee008a28c6c24be2ae5d0dad2df607201af975ec3cb4ea4f26d0dd1c6d05aa7a" +dependencies = [ + "itertools 0.12.1", + "log", + "percentage", + "serde", + "serde_derive", + "solana-bpf-loader-program", + "solana-compute-budget", + "solana-feature-set", + "solana-fee", + "solana-loader-v4-program", + "solana-log-collector", + "solana-measure", + "solana-program-runtime", + "solana-runtime-transaction", + "solana-sdk", + "solana-svm-rent-collector", + "solana-svm-transaction", + "solana-system-program", + "solana-timings", + "solana-type-overrides", + "solana-vote", + "thiserror 1.0.69", +] + +[[package]] +name = "solana-svm-rent-collector" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9c1360c7382ec61503aab743068c443fd235e1087adb71216de6f03612062a5" +dependencies = [ + "solana-sdk", +] + +[[package]] +name = "solana-svm-transaction" +version = "2.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cce3a10755daa103d6c5bcb119515e8a44db6c69d2e37b54704128e11c5356" +dependencies = [ + "solana-sdk", +] + [[package]] name = "solana-stake-interface" version = "1.2.1" @@ -7160,6 +7431,28 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "token-interface" +version = "0.0.0" +dependencies = [ + "pinocchio", + "pinocchio-pubkey", +] + +[[package]] +name = "token-program" +version = "0.0.0" +dependencies = [ + "assert_matches", + "pinocchio", + "pinocchio-log", + "solana-program-test", + "solana-sdk", + "spl-token 4.0.2", + "test-case", + "token-interface", +] + [[package]] name = "tokio" version = "1.43.0" From 293bb5af78d170fc7a3f41d5933739c01fbda570 Mon Sep 17 00:00:00 2001 From: febo Date: Thu, 13 Feb 2025 23:21:23 +0000 Subject: [PATCH 08/16] Rename interface crate --- Cargo.lock | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6de43135..dc1457fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7431,28 +7431,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "token-interface" -version = "0.0.0" -dependencies = [ - "pinocchio", - "pinocchio-pubkey", -] - -[[package]] -name = "token-program" -version = "0.0.0" -dependencies = [ - "assert_matches", - "pinocchio", - "pinocchio-log", - "solana-program-test", - "solana-sdk", - "spl-token 4.0.2", - "test-case", - "token-interface", -] - [[package]] name = "tokio" version = "1.43.0" From e0c5dfc992e1211fb104c7474efb074fa8ee45cd Mon Sep 17 00:00:00 2001 From: febo Date: Thu, 6 Feb 2025 00:46:38 +0000 Subject: [PATCH 09/16] Fix spelling --- Cargo.lock | 271 ----------------------------------------------------- 1 file changed, 271 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc1457fd..f30c2e0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2680,7 +2680,6 @@ checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc" dependencies = [ "cc", "libc", - "openssl-src", "pkg-config", "vcpkg", ] @@ -5461,173 +5460,6 @@ dependencies = [ "solana-sysvar-id", ] -[[package]] -name = "solana-rpc-client" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7b40d68b77b47a7786965eca51207dd19cb68bb518da7476e84cc4f87f5c334" -dependencies = [ - "async-trait", - "base64 0.22.1", - "bincode", - "bs58", - "indicatif", - "log", - "reqwest", - "reqwest-middleware", - "semver", - "serde", - "serde_derive", - "serde_json", - "solana-account-decoder-client-types", - "solana-rpc-client-api", - "solana-sdk", - "solana-transaction-status-client-types", - "solana-version", - "solana-vote-program", - "tokio", -] - -[[package]] -name = "solana-rpc-client-api" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4520467a0bb012c7ecf121eaae0182d4c3c0647844c6bbcbeea87997a9cdc97e" -dependencies = [ - "anyhow", - "base64 0.22.1", - "bs58", - "jsonrpc-core", - "reqwest", - "reqwest-middleware", - "semver", - "serde", - "serde_derive", - "serde_json", - "solana-account-decoder-client-types", - "solana-inline-spl", - "solana-sdk", - "solana-transaction-status-client-types", - "solana-version", - "thiserror 1.0.69", -] - -[[package]] -name = "solana-rpc-client-nonce-utils" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1396307c7e3a72ed8074cb1c31f7f6613d3e71f0f3414911ccbaeea29690158d" -dependencies = [ - "solana-rpc-client", - "solana-sdk", - "thiserror 1.0.69", -] - -[[package]] -name = "solana-runtime" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cebb07bfc23c41c5f63dd00f62a377e9d30903e551ddc570aced74ab729c340b" -dependencies = [ - "ahash", - "aquamarine", - "arrayref", - "base64 0.22.1", - "bincode", - "blake3", - "bv", - "bytemuck", - "byteorder", - "bzip2", - "crossbeam-channel", - "dashmap", - "dir-diff", - "flate2", - "fnv", - "im", - "index_list", - "itertools 0.12.1", - "lazy_static", - "libc", - "log", - "lz4", - "memmap2", - "mockall", - "modular-bitfield", - "num-derive", - "num-traits", - "num_cpus", - "num_enum", - "percentage", - "qualifier_attr", - "rand 0.8.5", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "serde_with", - "solana-accounts-db", - "solana-address-lookup-table-program", - "solana-bpf-loader-program", - "solana-bucket-map", - "solana-compute-budget", - "solana-compute-budget-program", - "solana-config-program", - "solana-cost-model", - "solana-feature-set", - "solana-fee", - "solana-inline-spl", - "solana-lattice-hash", - "solana-loader-v4-program", - "solana-measure", - "solana-metrics", - "solana-perf", - "solana-program", - "solana-program-runtime", - "solana-rayon-threadlimit", - "solana-runtime-transaction", - "solana-sdk", - "solana-stake-program", - "solana-svm", - "solana-svm-rent-collector", - "solana-svm-transaction", - "solana-system-program", - "solana-timings", - "solana-transaction-status", - "solana-version", - "solana-vote", - "solana-vote-program", - "solana-zk-elgamal-proof-program", - "solana-zk-sdk", - "solana-zk-token-proof-program", - "solana-zk-token-sdk", - "static_assertions", - "strum", - "strum_macros", - "symlink", - "tar", - "tempfile", - "thiserror 1.0.69", - "zstd", -] - -[[package]] -name = "solana-runtime-transaction" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "242b34f49b0c31f8f10681e4f0c15f4e5d49da7da89ce7f524e0877d5ce8e9cc" -dependencies = [ - "agave-transaction-view", - "log", - "solana-builtins-default-costs", - "solana-compute-budget", - "solana-pubkey", - "solana-sdk", - "solana-svm-transaction", - "thiserror 1.0.69", -] - [[package]] name = "solana-rent-collector" version = "2.2.1" @@ -6190,109 +6022,6 @@ dependencies = [ "solana-pubkey", ] -[[package]] -name = "solana-stake-program" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803aae3aa3c4b344bd6eb2107dd7a897f15b9614af4d5c6dbaf9026bc39a1fe" -dependencies = [ - "bincode", - "log", - "solana-config-program", - "solana-feature-set", - "solana-log-collector", - "solana-program-runtime", - "solana-sdk", - "solana-type-overrides", - "solana-vote-program", -] - -[[package]] -name = "solana-streamer" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85090db4563b271711d44275a20d1becb4a92e2fdeb41f5234b45df0321e807d" -dependencies = [ - "async-channel", - "bytes", - "crossbeam-channel", - "dashmap", - "futures", - "futures-util", - "governor", - "histogram", - "indexmap", - "itertools 0.12.1", - "libc", - "log", - "nix", - "pem", - "percentage", - "quinn", - "quinn-proto", - "rand 0.8.5", - "rustls 0.23.22", - "smallvec", - "socket2", - "solana-measure", - "solana-metrics", - "solana-perf", - "solana-sdk", - "solana-transaction-metrics-tracker", - "thiserror 1.0.69", - "tokio", - "tokio-util 0.7.13", - "x509-parser", -] - -[[package]] -name = "solana-svm" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee008a28c6c24be2ae5d0dad2df607201af975ec3cb4ea4f26d0dd1c6d05aa7a" -dependencies = [ - "itertools 0.12.1", - "log", - "percentage", - "serde", - "serde_derive", - "solana-bpf-loader-program", - "solana-compute-budget", - "solana-feature-set", - "solana-fee", - "solana-loader-v4-program", - "solana-log-collector", - "solana-measure", - "solana-program-runtime", - "solana-runtime-transaction", - "solana-sdk", - "solana-svm-rent-collector", - "solana-svm-transaction", - "solana-system-program", - "solana-timings", - "solana-type-overrides", - "solana-vote", - "thiserror 1.0.69", -] - -[[package]] -name = "solana-svm-rent-collector" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9c1360c7382ec61503aab743068c443fd235e1087adb71216de6f03612062a5" -dependencies = [ - "solana-sdk", -] - -[[package]] -name = "solana-svm-transaction" -version = "2.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cce3a10755daa103d6c5bcb119515e8a44db6c69d2e37b54704128e11c5356" -dependencies = [ - "solana-sdk", -] - [[package]] name = "solana-stake-interface" version = "1.2.1" From a91636f06fb9f5331bb9b737ac782be41a314126 Mon Sep 17 00:00:00 2001 From: febo Date: Wed, 5 Mar 2025 14:14:58 +0000 Subject: [PATCH 10/16] [wip]: Fix review comments --- p-token/src/entrypoint.rs | 51 ++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/p-token/src/entrypoint.rs b/p-token/src/entrypoint.rs index 4483f023..579491f8 100644 --- a/p-token/src/entrypoint.rs +++ b/p-token/src/entrypoint.rs @@ -2,6 +2,7 @@ use pinocchio::{ account_info::AccountInfo, default_panic_handler, no_allocator, program_entrypoint, program_error::ProgramError, pubkey::Pubkey, ProgramResult, }; +use spl_token_interface::instruction::TokenInstruction; use crate::processor::*; @@ -66,9 +67,9 @@ pub(crate) fn inner_process_instruction( return Err(ProgramError::InvalidInstructionData); }; - match *discriminator { + match instruction { // 0 - InitializeMint - 0 => { + TokenInstruction::InitializeMint => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: InitializeMint"); @@ -82,21 +83,21 @@ pub(crate) fn inner_process_instruction( process_initialize_account(accounts) } // 3 - Transfer - 3 => { + TokenInstruction::Transfer => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: Transfer"); process_transfer(accounts, instruction_data) } // 7 - MintTo - 7 => { + TokenInstruction::MintTo => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: MintTo"); process_mint_to(accounts, instruction_data) } // 9 - CloseAccount - 9 => { + TokenInstruction::CloseAccount => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: CloseAccount"); @@ -110,14 +111,14 @@ pub(crate) fn inner_process_instruction( process_initialize_account2(accounts, instruction_data) } // 18 - InitializeAccount3 - 18 => { + TokenInstruction::InitializeAccount3 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: InitializeAccount3"); process_initialize_account3(accounts, instruction_data) } // 20 - InitializeMint2 - 20 => { + TokenInstruction::InitializeMint2 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: InitializeMint2"); @@ -135,123 +136,123 @@ pub(crate) fn inner_process_instruction( fn inner_process_remaining_instruction( accounts: &[AccountInfo], instruction_data: &[u8], - discriminator: u8, + instruction: TokenInstruction, ) -> ProgramResult { match discriminator { // 2 - InitializeMultisig - 2 => { + TokenInstruction::InitializeMultisig => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: InitializeMultisig"); process_initialize_multisig(accounts, instruction_data) } // 4 - Approve - 4 => { + TokenInstruction::Approve => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: Approve"); process_approve(accounts, instruction_data) } // 5 - Revoke - 5 => { + TokenInstruction::Revoke => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: Revoke"); process_revoke(accounts, instruction_data) } // 6 - SetAuthority - 6 => { + TokenInstruction::SetAuthority => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: SetAuthority"); process_set_authority(accounts, instruction_data) } // 8 - Burn - 8 => { + TokenInstruction::Burn => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: Burn"); process_burn(accounts, instruction_data) } // 10 - FreezeAccount - 10 => { + TokenInstruction::FreezeAccount => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: FreezeAccount"); process_freeze_account(accounts) } // 11 - ThawAccount - 11 => { + TokenInstruction::ThawAccount => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: ThawAccount"); process_thaw_account(accounts) } // 12 - TransferChecked - 12 => { + TokenInstruction::TransferChecked => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: TransferChecked"); process_transfer_checked(accounts, instruction_data) } // 13 - ApproveChecked - 13 => { + TokenInstruction::ApproveChecked => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: ApproveChecked"); process_approve_checked(accounts, instruction_data) } // 14 - MintToChecked - 14 => { + TokenInstruction::MintToChecked => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: MintToChecked"); process_mint_to_checked(accounts, instruction_data) } // 15 - BurnChecked - 15 => { + TokenInstruction::BurnChecked => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: BurnChecked"); process_burn_checked(accounts, instruction_data) } // 17 - SyncNative - 17 => { + TokenInstruction::SyncNative => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: SyncNative"); process_sync_native(accounts) } // 19 - InitializeMultisig2 - 19 => { + TokenInstruction::InitializeMultisig2 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: InitializeMultisig2"); process_initialize_multisig2(accounts, instruction_data) } // 21 - GetAccountDataSize - 21 => { + TokenInstruction::GetAccountDataSize => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: GetAccountDataSize"); process_get_account_data_size(accounts) } // 22 - InitializeImmutableOwner - 22 => { + TokenInstruction::InitializeImmutableOwner => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: InitializeImmutableOwner"); process_initialize_immutable_owner(accounts) } // 23 - AmountToUiAmount - 23 => { + TokenInstruction::AmountToUiAmount => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: AmountToUiAmount"); process_amount_to_ui_amount(accounts, instruction_data) } // 24 - UiAmountToAmount - 24 => { + TokenInstruction::UiAmountToAmount => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: UiAmountToAmount"); From 73150362e282a25eb594eb2472190b133e8a5664 Mon Sep 17 00:00:00 2001 From: febo Date: Fri, 7 Mar 2025 03:10:24 +0000 Subject: [PATCH 11/16] Add withdraw_excess_lamports instruction --- interface/src/instruction.rs | 14 +++- p-token/src/entrypoint.rs | 7 ++ p-token/src/processor/mod.rs | 2 + .../src/processor/withdraw_excess_lamports.rs | 74 +++++++++++++++++++ 4 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 p-token/src/processor/withdraw_excess_lamports.rs diff --git a/interface/src/instruction.rs b/interface/src/instruction.rs index 6de462c9..5b7b0ea5 100644 --- a/interface/src/instruction.rs +++ b/interface/src/instruction.rs @@ -478,6 +478,18 @@ pub enum TokenInstruction { /// - `&str` The `ui_amount` of tokens to reformat. UiAmountToAmount, + /// This instruction is to be used to rescue SOL sent to any `TokenProgram` + /// owned account by sending them to any other account, leaving behind only + /// lamports for rent exemption. + /// + /// Accounts expected by this instruction: + /// + /// 0. `[writable]` Source Account owned by the token program + /// 1. `[writable]` Destination account + /// 2. `[signer]` Authority + /// 3. `..+M` `[signer]` M signer accounts. + WithdrawExcessLamports = 38, + /// Executes a batch of instructions. The instructions to be executed are specified /// in sequence on the instruction data. Each instruction provides: /// - `u8`: number of accounts @@ -506,7 +518,7 @@ impl TryFrom for TokenInstruction { fn try_from(value: u8) -> Result { match value { // SAFETY: `value` is guaranteed to be in the range of the enum variants. - 0..=24 | 255 => Ok(unsafe { core::mem::transmute::(value) }), + 0..=24 | 38 | 255 => Ok(unsafe { core::mem::transmute::(value) }), _ => Err(ProgramError::InvalidInstructionData), } } diff --git a/p-token/src/entrypoint.rs b/p-token/src/entrypoint.rs index 579491f8..85965383 100644 --- a/p-token/src/entrypoint.rs +++ b/p-token/src/entrypoint.rs @@ -258,6 +258,13 @@ fn inner_process_remaining_instruction( process_ui_amount_to_amount(accounts, instruction_data) } + // 38 - WithdrawExcessLamports + 38 => { + #[cfg(feature = "logging")] + pinocchio::msg!("Instruction: WithdrawExcessLamports"); + + process_withdraw_excess_lamports(accounts) + } _ => Err(ProgramError::InvalidInstructionData), } } diff --git a/p-token/src/processor/mod.rs b/p-token/src/processor/mod.rs index 0002c0f9..5182e83e 100644 --- a/p-token/src/processor/mod.rs +++ b/p-token/src/processor/mod.rs @@ -39,6 +39,7 @@ pub mod thaw_account; pub mod transfer; pub mod transfer_checked; pub mod ui_amount_to_amount; +pub mod withdraw_excess_lamports; // Shared processors. pub mod shared; @@ -68,6 +69,7 @@ pub use thaw_account::process_thaw_account; pub use transfer::process_transfer; pub use transfer_checked::process_transfer_checked; pub use ui_amount_to_amount::process_ui_amount_to_amount; +pub use withdraw_excess_lamports::process_withdraw_excess_lamports; /// Maximum number of digits in a formatted `u64`. /// diff --git a/p-token/src/processor/withdraw_excess_lamports.rs b/p-token/src/processor/withdraw_excess_lamports.rs new file mode 100644 index 00000000..6fdd0b37 --- /dev/null +++ b/p-token/src/processor/withdraw_excess_lamports.rs @@ -0,0 +1,74 @@ +use pinocchio::{ + account_info::AccountInfo, + program_error::ProgramError, + sysvars::{rent::Rent, Sysvar}, + ProgramResult, +}; +use spl_token_interface::{ + error::TokenError, + state::{account::Account, load, mint::Mint, multisig::Multisig, Transmutable}, +}; + +use super::validate_owner; + +#[inline(always)] +pub fn process_withdraw_excess_lamports(accounts: &[AccountInfo]) -> ProgramResult { + let [source_account_info, destination_info, authority_info, remaining @ ..] = accounts else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + + // SAFETY: single mutable borrow to `source_account_info` account data + let source_data = unsafe { source_account_info.borrow_data_unchecked() }; + + match source_data.len() { + Account::LEN => { + let account = unsafe { load::(source_data)? }; + + if account.is_native() { + return Err(TokenError::NativeNotSupported.into()); + } + + validate_owner(&account.owner, authority_info, remaining)?; + } + Mint::LEN => { + let mint = unsafe { load::(source_data)? }; + + if let Some(mint_authority) = mint.mint_authority() { + validate_owner(mint_authority, authority_info, remaining)?; + } else { + return Err(TokenError::AuthorityTypeNotSupported.into()); + } + } + Multisig::LEN => { + validate_owner(source_account_info.key(), authority_info, remaining)?; + } + _ => return Err(TokenError::InvalidState.into()), + } + + let source_rent_exempt_reserve = Rent::get()?.minimum_balance(source_data.len()); + + let transfer_amount = source_account_info + .lamports() + .checked_sub(source_rent_exempt_reserve) + .ok_or(TokenError::NotRentExempt)?; + + let source_starting_lamports = source_account_info.lamports(); + // SAFETY: single mutable borrow to `source_account_info` lamports. + unsafe { + // Moves the lamports out of the source account. + *source_account_info.borrow_mut_lamports_unchecked() = source_starting_lamports + .checked_sub(transfer_amount) + .ok_or(TokenError::Overflow)?; + } + + let destination_starting_lamports = destination_info.lamports(); + // SAFETY: single mutable borrow to `destination_info` lamports. + unsafe { + // Moves the lamports to the destination account. + *destination_info.borrow_mut_lamports_unchecked() = destination_starting_lamports + .checked_add(transfer_amount) + .ok_or(TokenError::Overflow)?; + } + + Ok(()) +} From 98d7e299ea2f52408b06430903cb6f72a4d745ec Mon Sep 17 00:00:00 2001 From: febo Date: Fri, 7 Mar 2025 10:21:04 +0000 Subject: [PATCH 12/16] Add test --- Cargo.lock | 1 + p-token/Cargo.toml | 1 + .../src/processor/withdraw_excess_lamports.rs | 10 +- p-token/tests/withdraw_excess_lamports.rs | 111 ++++++++++++++++++ 4 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 p-token/tests/withdraw_excess_lamports.rs diff --git a/Cargo.lock b/Cargo.lock index f30c2e0f..f719d2ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2845,6 +2845,7 @@ dependencies = [ "solana-program-test", "solana-sdk", "spl-token 4.0.2", + "spl-token-2022 7.0.0", "spl-token-interface", "test-case", ] diff --git a/p-token/Cargo.toml b/p-token/Cargo.toml index d8769984..f59ac39e 100644 --- a/p-token/Cargo.toml +++ b/p-token/Cargo.toml @@ -24,4 +24,5 @@ assert_matches = "1.5.0" solana-program-test = "2.1" solana-sdk = "2.1" spl-token = { version="^4", features=["no-entrypoint"] } +spl-token-2022 = { version="^7", features=["no-entrypoint"] } test-case = "3.3.1" diff --git a/p-token/src/processor/withdraw_excess_lamports.rs b/p-token/src/processor/withdraw_excess_lamports.rs index 6fdd0b37..3a65bdae 100644 --- a/p-token/src/processor/withdraw_excess_lamports.rs +++ b/p-token/src/processor/withdraw_excess_lamports.rs @@ -45,6 +45,8 @@ pub fn process_withdraw_excess_lamports(accounts: &[AccountInfo]) -> ProgramResu _ => return Err(TokenError::InvalidState.into()), } + // Withdraws the excess lamports from the source account. + let source_rent_exempt_reserve = Rent::get()?.minimum_balance(source_data.len()); let transfer_amount = source_account_info @@ -56,9 +58,11 @@ pub fn process_withdraw_excess_lamports(accounts: &[AccountInfo]) -> ProgramResu // SAFETY: single mutable borrow to `source_account_info` lamports. unsafe { // Moves the lamports out of the source account. - *source_account_info.borrow_mut_lamports_unchecked() = source_starting_lamports - .checked_sub(transfer_amount) - .ok_or(TokenError::Overflow)?; + // + // Note: The `transfer_amount` is guaranteed to be less than the source account's + // lamports. + *source_account_info.borrow_mut_lamports_unchecked() = + source_starting_lamports - transfer_amount; } let destination_starting_lamports = destination_info.lamports(); diff --git a/p-token/tests/withdraw_excess_lamports.rs b/p-token/tests/withdraw_excess_lamports.rs new file mode 100644 index 00000000..3f3bae15 --- /dev/null +++ b/p-token/tests/withdraw_excess_lamports.rs @@ -0,0 +1,111 @@ +#![cfg(feature = "test-sbf")] + +mod setup; + +use std::mem::size_of; + +use setup::TOKEN_PROGRAM_ID; +use solana_program_test::{tokio, ProgramTest}; +use solana_sdk::{ + pubkey::Pubkey, + signature::{Keypair, Signer}, + system_instruction, + transaction::Transaction, +}; +use spl_token_interface::state::mint::Mint; + +const EXCESS_LAMPORTS: u64 = 1_000_000_000; + +#[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")] +#[tokio::test] +async fn withdraw_excess_lamports(token_program: Pubkey) { + let context = ProgramTest::new("pinocchio_token_program", TOKEN_PROGRAM_ID, None) + .start_with_context() + .await; + + // Given a mint authority, freeze authority and an account keypair. + + let mint_authority = Keypair::new(); + let freeze_authority = Pubkey::new_unique(); + let account = Keypair::new(); + let account_pubkey = account.pubkey(); + + let account_size = size_of::(); + let rent = context.banks_client.get_rent().await.unwrap(); + + let mut initialize_ix = spl_token::instruction::initialize_mint( + &spl_token::ID, + &account.pubkey(), + &mint_authority.pubkey(), + Some(&freeze_authority), + 0, + ) + .unwrap(); + // Switches the program id to the token program. + initialize_ix.program_id = token_program; + + // And we initialize a mint account with excess lamports. + + let instructions = vec![ + system_instruction::create_account( + &context.payer.pubkey(), + &account.pubkey(), + rent.minimum_balance(account_size) + EXCESS_LAMPORTS, + account_size as u64, + &token_program, + ), + initialize_ix, + ]; + + let tx = Transaction::new_signed_with_payer( + &instructions, + Some(&context.payer.pubkey()), + &[&context.payer, &account], + context.last_blockhash, + ); + context.banks_client.process_transaction(tx).await.unwrap(); + + let account = context + .banks_client + .get_account(account.pubkey()) + .await + .unwrap(); + + assert!(account.is_some()); + + let account = account.unwrap(); + assert_eq!( + account.lamports, + rent.minimum_balance(account_size) + EXCESS_LAMPORTS + ); + + // When we withdraw the excess lamports. + + let destination = Pubkey::new_unique(); + + let mut withdraw_ix = spl_token_2022::instruction::withdraw_excess_lamports( + &spl_token_2022::ID, + &account_pubkey, + &destination, + &mint_authority.pubkey(), + &[], + ) + .unwrap(); + // Switches the program id to the token program. + withdraw_ix.program_id = token_program; + + let tx = Transaction::new_signed_with_payer( + &[withdraw_ix], + Some(&context.payer.pubkey()), + &[&context.payer, &mint_authority], + context.last_blockhash, + ); + context.banks_client.process_transaction(tx).await.unwrap(); + + let destination = context.banks_client.get_account(destination).await.unwrap(); + + assert!(destination.is_some()); + + let destination = destination.unwrap(); + assert_eq!(destination.lamports, EXCESS_LAMPORTS); +} From 32383b633ae7621b7766a64cb605c1b3fd2a34e2 Mon Sep 17 00:00:00 2001 From: febo Date: Fri, 7 Mar 2025 10:31:44 +0000 Subject: [PATCH 13/16] Add missing safety comments --- p-token/src/processor/withdraw_excess_lamports.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/p-token/src/processor/withdraw_excess_lamports.rs b/p-token/src/processor/withdraw_excess_lamports.rs index 3a65bdae..44e9015a 100644 --- a/p-token/src/processor/withdraw_excess_lamports.rs +++ b/p-token/src/processor/withdraw_excess_lamports.rs @@ -22,6 +22,7 @@ pub fn process_withdraw_excess_lamports(accounts: &[AccountInfo]) -> ProgramResu match source_data.len() { Account::LEN => { + // SAFETY: `source_data` has the same length as `Account`. let account = unsafe { load::(source_data)? }; if account.is_native() { @@ -31,6 +32,7 @@ pub fn process_withdraw_excess_lamports(accounts: &[AccountInfo]) -> ProgramResu validate_owner(&account.owner, authority_info, remaining)?; } Mint::LEN => { + // SAFETY: `source_data` has the same length as `Mint`. let mint = unsafe { load::(source_data)? }; if let Some(mint_authority) = mint.mint_authority() { From 73443de5a7dc56844f80af552a9835f19541b564 Mon Sep 17 00:00:00 2001 From: febo Date: Fri, 7 Mar 2025 13:26:18 +0000 Subject: [PATCH 14/16] Add more tests --- Cargo.lock | 1 + p-token/Cargo.toml | 1 + p-token/tests/setup/mod.rs | 43 ++ p-token/tests/withdraw_excess_lamports.rs | 639 +++++++++++++++++++++- 4 files changed, 676 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f719d2ee..3b7cd351 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2840,6 +2840,7 @@ name = "pinocchio-token-program" version = "0.0.0" dependencies = [ "assert_matches", + "num-traits", "pinocchio", "pinocchio-log", "solana-program-test", diff --git a/p-token/Cargo.toml b/p-token/Cargo.toml index f59ac39e..03d61893 100644 --- a/p-token/Cargo.toml +++ b/p-token/Cargo.toml @@ -21,6 +21,7 @@ spl-token-interface = { version = "^0", path = "../interface" } [dev-dependencies] assert_matches = "1.5.0" +num-traits = "0.2" solana-program-test = "2.1" solana-sdk = "2.1" spl-token = { version="^4", features=["no-entrypoint"] } diff --git a/p-token/tests/setup/mod.rs b/p-token/tests/setup/mod.rs index c607de27..5871bfa8 100644 --- a/p-token/tests/setup/mod.rs +++ b/p-token/tests/setup/mod.rs @@ -6,3 +6,46 @@ pub mod account; pub mod mint; pub const TOKEN_PROGRAM_ID: Pubkey = Pubkey::new_from_array(spl_token_interface::program::ID); + +#[macro_export] +macro_rules! assert_instruction_error { + ( $error:expr, $matcher:pat ) => { + match $error { + solana_program_test::BanksClientError::TransactionError( + solana_sdk::transaction::TransactionError::InstructionError(_, $matcher), + ) => { + assert!(true) + } + err => assert!(false, "Expected instruction error but got '{:#?}'", err), + }; + }; +} + +#[macro_export] +macro_rules! assert_custom_error { + ( $error:expr, $matcher:pat ) => { + match $error { + solana_program_test::BanksClientError::TransactionError( + solana_sdk::transaction::TransactionError::InstructionError( + _, + solana_sdk::instruction::InstructionError::Custom(x), + ), + ) => match num_traits::FromPrimitive::from_i32(x as i32) { + Some($matcher) => assert!(true), + Some(other) => { + assert!( + false, + "Expected another custom instruction error than '{:#?}'", + other + ) + } + None => assert!(false, "Expected custom instruction error"), + }, + err => assert!( + false, + "Expected custom instruction error but got '{:#?}'", + err + ), + }; + }; +} diff --git a/p-token/tests/withdraw_excess_lamports.rs b/p-token/tests/withdraw_excess_lamports.rs index 3f3bae15..05bba6ba 100644 --- a/p-token/tests/withdraw_excess_lamports.rs +++ b/p-token/tests/withdraw_excess_lamports.rs @@ -4,25 +4,26 @@ mod setup; use std::mem::size_of; -use setup::TOKEN_PROGRAM_ID; +use setup::{mint, TOKEN_PROGRAM_ID}; use solana_program_test::{tokio, ProgramTest}; use solana_sdk::{ + instruction::InstructionError, pubkey::Pubkey, signature::{Keypair, Signer}, system_instruction, transaction::Transaction, }; -use spl_token_interface::state::mint::Mint; - -const EXCESS_LAMPORTS: u64 = 1_000_000_000; +use spl_token_interface::state::{account::Account, mint::Mint, multisig::Multisig}; #[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")] #[tokio::test] -async fn withdraw_excess_lamports(token_program: Pubkey) { +async fn withdraw_excess_lamports_from_mint(token_program: Pubkey) { let context = ProgramTest::new("pinocchio_token_program", TOKEN_PROGRAM_ID, None) .start_with_context() .await; + let excess_lamports = 4_000_000_000_000; + // Given a mint authority, freeze authority and an account keypair. let mint_authority = Keypair::new(); @@ -50,7 +51,7 @@ async fn withdraw_excess_lamports(token_program: Pubkey) { system_instruction::create_account( &context.payer.pubkey(), &account.pubkey(), - rent.minimum_balance(account_size) + EXCESS_LAMPORTS, + rent.minimum_balance(account_size) + excess_lamports, account_size as u64, &token_program, ), @@ -76,7 +77,7 @@ async fn withdraw_excess_lamports(token_program: Pubkey) { let account = account.unwrap(); assert_eq!( account.lamports, - rent.minimum_balance(account_size) + EXCESS_LAMPORTS + rent.minimum_balance(account_size) + excess_lamports ); // When we withdraw the excess lamports. @@ -102,10 +103,632 @@ async fn withdraw_excess_lamports(token_program: Pubkey) { ); context.banks_client.process_transaction(tx).await.unwrap(); + // Then the destination account has the excess lamports. + let destination = context.banks_client.get_account(destination).await.unwrap(); assert!(destination.is_some()); let destination = destination.unwrap(); - assert_eq!(destination.lamports, EXCESS_LAMPORTS); + assert_eq!(destination.lamports, excess_lamports); +} + +#[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")] +#[tokio::test] +async fn withdraw_excess_lamports_from_account(token_program: Pubkey) { + let mut context = ProgramTest::new("pinocchio_token_program", TOKEN_PROGRAM_ID, None) + .start_with_context() + .await; + + let excess_lamports = 4_000_000_000_000; + + // Given a mint account. + + let mint_authority = Pubkey::new_unique(); + let freeze_authority = Pubkey::new_unique(); + + let mint = mint::initialize( + &mut context, + mint_authority, + Some(freeze_authority), + &token_program, + ) + .await + .unwrap(); + + // Given a mint authority, freeze authority and an account keypair. + + let owner = Keypair::new(); + let account = Keypair::new(); + let account_pubkey = account.pubkey(); + + let account_size = size_of::(); + let rent = context.banks_client.get_rent().await.unwrap(); + + let mut initialize_ix = spl_token::instruction::initialize_account( + &spl_token::ID, + &account.pubkey(), + &mint, + &owner.pubkey(), + ) + .unwrap(); + // Switches the program id to the token program. + initialize_ix.program_id = token_program; + + // When a new mint account is created and initialized. + + let instructions = vec![ + system_instruction::create_account( + &context.payer.pubkey(), + &account.pubkey(), + rent.minimum_balance(account_size) + excess_lamports, + account_size as u64, + &token_program, + ), + initialize_ix, + ]; + + let tx = Transaction::new_signed_with_payer( + &instructions, + Some(&context.payer.pubkey()), + &[&context.payer, &account], + context.last_blockhash, + ); + context.banks_client.process_transaction(tx).await.unwrap(); + + let account = context + .banks_client + .get_account(account.pubkey()) + .await + .unwrap(); + + assert!(account.is_some()); + + let account = account.unwrap(); + assert_eq!( + account.lamports, + rent.minimum_balance(account_size) + excess_lamports + ); + + // When we withdraw the excess lamports. + + let destination = Pubkey::new_unique(); + + let mut withdraw_ix = spl_token_2022::instruction::withdraw_excess_lamports( + &spl_token_2022::ID, + &account_pubkey, + &destination, + &owner.pubkey(), + &[], + ) + .unwrap(); + // Switches the program id to the token program. + withdraw_ix.program_id = token_program; + + let tx = Transaction::new_signed_with_payer( + &[withdraw_ix], + Some(&context.payer.pubkey()), + &[&context.payer, &owner], + context.last_blockhash, + ); + context.banks_client.process_transaction(tx).await.unwrap(); + + // Then the destination account has the excess lamports. + + let destination = context.banks_client.get_account(destination).await.unwrap(); + + assert!(destination.is_some()); + + let destination = destination.unwrap(); + assert_eq!(destination.lamports, excess_lamports); +} + +#[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")] +#[tokio::test] +async fn withdraw_excess_lamports_from_multisig(token_program: Pubkey) { + let context = ProgramTest::new("pinocchio_token_program", TOKEN_PROGRAM_ID, None) + .start_with_context() + .await; + + let excess_lamports = 4_000_000_000_000; + + // Given an account + + let multisig = Keypair::new(); + let signer1 = Keypair::new(); + let signer1_pubkey = signer1.pubkey(); + let signer2 = Keypair::new(); + let signer2_pubkey = signer2.pubkey(); + let signer3 = Keypair::new(); + let signer3_pubkey = signer3.pubkey(); + let signers = vec![&signer1_pubkey, &signer2_pubkey, &signer3_pubkey]; + + let rent = context.banks_client.get_rent().await.unwrap(); + let account_size = size_of::(); + + let mut initialize_ix = spl_token::instruction::initialize_multisig( + &spl_token::ID, + &multisig.pubkey(), + &signers, + 3, + ) + .unwrap(); + // Switches the program id to the token program. + initialize_ix.program_id = token_program; + + // And we initialize the multisig account. + + let instructions = vec![ + system_instruction::create_account( + &context.payer.pubkey(), + &multisig.pubkey(), + rent.minimum_balance(account_size) + excess_lamports, + account_size as u64, + &token_program, + ), + initialize_ix, + ]; + + let tx = Transaction::new_signed_with_payer( + &instructions, + Some(&context.payer.pubkey()), + &[&context.payer, &multisig], + context.last_blockhash, + ); + context.banks_client.process_transaction(tx).await.unwrap(); + + let account = context + .banks_client + .get_account(multisig.pubkey()) + .await + .unwrap(); + + assert!(account.is_some()); + + let account = account.unwrap(); + assert_eq!( + account.lamports, + rent.minimum_balance(account_size) + excess_lamports + ); + + // When we withdraw the excess lamports. + + let destination = Pubkey::new_unique(); + + let mut withdraw_ix = spl_token_2022::instruction::withdraw_excess_lamports( + &spl_token_2022::ID, + &multisig.pubkey(), + &destination, + &multisig.pubkey(), + &signers, + ) + .unwrap(); + // Switches the program id to the token program. + withdraw_ix.program_id = token_program; + + let tx = Transaction::new_signed_with_payer( + &[withdraw_ix], + Some(&context.payer.pubkey()), + &[&context.payer, &signer1, &signer2, &signer3], + context.last_blockhash, + ); + context.banks_client.process_transaction(tx).await.unwrap(); + + // Then the destination account has the excess lamports. + + let destination = context.banks_client.get_account(destination).await.unwrap(); + + assert!(destination.is_some()); + + let destination = destination.unwrap(); + assert_eq!(destination.lamports, excess_lamports); +} + +#[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")] +#[tokio::test] +async fn fail_withdraw_excess_lamports_from_mint_wrong_authority(token_program: Pubkey) { + let context = ProgramTest::new("pinocchio_token_program", TOKEN_PROGRAM_ID, None) + .start_with_context() + .await; + + let excess_lamports = 4_000_000_000_000; + + // Given a mint authority, freeze authority and an account keypair. + + let mint_authority = Keypair::new(); + let freeze_authority = Pubkey::new_unique(); + let account = Keypair::new(); + let account_pubkey = account.pubkey(); + + let account_size = size_of::(); + let rent = context.banks_client.get_rent().await.unwrap(); + + let mut initialize_ix = spl_token::instruction::initialize_mint( + &spl_token::ID, + &account.pubkey(), + &mint_authority.pubkey(), + Some(&freeze_authority), + 0, + ) + .unwrap(); + // Switches the program id to the token program. + initialize_ix.program_id = token_program; + + // And we initialize a mint account with excess lamports. + + let instructions = vec![ + system_instruction::create_account( + &context.payer.pubkey(), + &account.pubkey(), + rent.minimum_balance(account_size) + excess_lamports, + account_size as u64, + &token_program, + ), + initialize_ix, + ]; + + let tx = Transaction::new_signed_with_payer( + &instructions, + Some(&context.payer.pubkey()), + &[&context.payer, &account], + context.last_blockhash, + ); + context.banks_client.process_transaction(tx).await.unwrap(); + + let account = context + .banks_client + .get_account(account.pubkey()) + .await + .unwrap(); + + assert!(account.is_some()); + + let account = account.unwrap(); + assert_eq!( + account.lamports, + rent.minimum_balance(account_size) + excess_lamports + ); + + // When we try to withdraw the excess lamports with the wrong authority. + + let destination = Pubkey::new_unique(); + let wrong_authority = Keypair::new(); + + let mut withdraw_ix = spl_token_2022::instruction::withdraw_excess_lamports( + &spl_token_2022::ID, + &account_pubkey, + &destination, + &wrong_authority.pubkey(), + &[], + ) + .unwrap(); + // Switches the program id to the token program. + withdraw_ix.program_id = token_program; + + let tx = Transaction::new_signed_with_payer( + &[withdraw_ix], + Some(&context.payer.pubkey()), + &[&context.payer, &wrong_authority], + context.last_blockhash, + ); + let error = context + .banks_client + .process_transaction(tx) + .await + .unwrap_err(); + + // The we expect an error. + + assert_custom_error!(error, spl_token::error::TokenError::OwnerMismatch); +} + +#[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")] +#[tokio::test] +async fn fail_withdraw_excess_lamports_from_account_wrong_authority(token_program: Pubkey) { + let mut context = ProgramTest::new("pinocchio_token_program", TOKEN_PROGRAM_ID, None) + .start_with_context() + .await; + + let excess_lamports = 4_000_000_000_000; + + // Given a mint account. + + let mint_authority = Pubkey::new_unique(); + let freeze_authority = Pubkey::new_unique(); + + let mint = mint::initialize( + &mut context, + mint_authority, + Some(freeze_authority), + &token_program, + ) + .await + .unwrap(); + + // Given a mint authority, freeze authority and an account keypair. + + let owner = Keypair::new(); + let account = Keypair::new(); + let account_pubkey = account.pubkey(); + + let account_size = size_of::(); + let rent = context.banks_client.get_rent().await.unwrap(); + + let mut initialize_ix = spl_token::instruction::initialize_account( + &spl_token::ID, + &account.pubkey(), + &mint, + &owner.pubkey(), + ) + .unwrap(); + // Switches the program id to the token program. + initialize_ix.program_id = token_program; + + // When a new mint account is created and initialized. + + let instructions = vec![ + system_instruction::create_account( + &context.payer.pubkey(), + &account.pubkey(), + rent.minimum_balance(account_size) + excess_lamports, + account_size as u64, + &token_program, + ), + initialize_ix, + ]; + + let tx = Transaction::new_signed_with_payer( + &instructions, + Some(&context.payer.pubkey()), + &[&context.payer, &account], + context.last_blockhash, + ); + context.banks_client.process_transaction(tx).await.unwrap(); + + let account = context + .banks_client + .get_account(account.pubkey()) + .await + .unwrap(); + + assert!(account.is_some()); + + let account = account.unwrap(); + assert_eq!( + account.lamports, + rent.minimum_balance(account_size) + excess_lamports + ); + + // When we try to withdraw the excess lamports with the wrong owner. + + let destination = Pubkey::new_unique(); + let wrong_owner = Keypair::new(); + + let mut withdraw_ix = spl_token_2022::instruction::withdraw_excess_lamports( + &spl_token_2022::ID, + &account_pubkey, + &destination, + &wrong_owner.pubkey(), + &[], + ) + .unwrap(); + // Switches the program id to the token program. + withdraw_ix.program_id = token_program; + + let tx = Transaction::new_signed_with_payer( + &[withdraw_ix], + Some(&context.payer.pubkey()), + &[&context.payer, &wrong_owner], + context.last_blockhash, + ); + let error = context + .banks_client + .process_transaction(tx) + .await + .unwrap_err(); + + // The we expect an error. + + assert_custom_error!(error, spl_token::error::TokenError::OwnerMismatch); +} + +#[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")] +#[tokio::test] +async fn fail_withdraw_excess_lamports_from_multisig_wrong_authority(token_program: Pubkey) { + let context = ProgramTest::new("pinocchio_token_program", TOKEN_PROGRAM_ID, None) + .start_with_context() + .await; + + let excess_lamports = 4_000_000_000_000; + + // Given an account + + let multisig = Keypair::new(); + let signer1 = Keypair::new(); + let signer1_pubkey = signer1.pubkey(); + let signer2 = Keypair::new(); + let signer2_pubkey = signer2.pubkey(); + let signer3 = Keypair::new(); + let signer3_pubkey = signer3.pubkey(); + let signers = vec![&signer1_pubkey, &signer2_pubkey, &signer3_pubkey]; + + let rent = context.banks_client.get_rent().await.unwrap(); + let account_size = size_of::(); + + let mut initialize_ix = spl_token::instruction::initialize_multisig( + &spl_token::ID, + &multisig.pubkey(), + &signers, + 3, + ) + .unwrap(); + // Switches the program id to the token program. + initialize_ix.program_id = token_program; + + // And we initialize the multisig account. + + let instructions = vec![ + system_instruction::create_account( + &context.payer.pubkey(), + &multisig.pubkey(), + rent.minimum_balance(account_size) + excess_lamports, + account_size as u64, + &token_program, + ), + initialize_ix, + ]; + + let tx = Transaction::new_signed_with_payer( + &instructions, + Some(&context.payer.pubkey()), + &[&context.payer, &multisig], + context.last_blockhash, + ); + context.banks_client.process_transaction(tx).await.unwrap(); + + let account = context + .banks_client + .get_account(multisig.pubkey()) + .await + .unwrap(); + + assert!(account.is_some()); + + let account = account.unwrap(); + assert_eq!( + account.lamports, + rent.minimum_balance(account_size) + excess_lamports + ); + + // When we try to withdraw the excess lamports with the wrong authority. + + let destination = Pubkey::new_unique(); + let wrong_authority = Keypair::new(); + + let mut withdraw_ix = spl_token_2022::instruction::withdraw_excess_lamports( + &spl_token_2022::ID, + &multisig.pubkey(), + &destination, + &wrong_authority.pubkey(), + &signers, + ) + .unwrap(); + // Switches the program id to the token program. + withdraw_ix.program_id = token_program; + + let tx = Transaction::new_signed_with_payer( + &[withdraw_ix], + Some(&context.payer.pubkey()), + &[&context.payer, &signer1, &signer2, &signer3], + context.last_blockhash, + ); + let error = context + .banks_client + .process_transaction(tx) + .await + .unwrap_err(); + + // The we expect an error. + + assert_custom_error!(error, spl_token::error::TokenError::OwnerMismatch); +} + +#[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")] +#[tokio::test] +async fn fail_withdraw_excess_lamports_from_multisig_missing_signer(token_program: Pubkey) { + let context = ProgramTest::new("pinocchio_token_program", TOKEN_PROGRAM_ID, None) + .start_with_context() + .await; + + let excess_lamports = 4_000_000_000_000; + + // Given an account + + let multisig = Keypair::new(); + let signer1 = Keypair::new(); + let signer1_pubkey = signer1.pubkey(); + let signer2 = Keypair::new(); + let signer2_pubkey = signer2.pubkey(); + let signer3 = Keypair::new(); + let signer3_pubkey = signer3.pubkey(); + let signers = vec![&signer1_pubkey, &signer2_pubkey, &signer3_pubkey]; + + let rent = context.banks_client.get_rent().await.unwrap(); + let account_size = size_of::(); + + let mut initialize_ix = spl_token::instruction::initialize_multisig( + &spl_token::ID, + &multisig.pubkey(), + &signers, + 3, + ) + .unwrap(); + // Switches the program id to the token program. + initialize_ix.program_id = token_program; + + // And we initialize the multisig account. + + let instructions = vec![ + system_instruction::create_account( + &context.payer.pubkey(), + &multisig.pubkey(), + rent.minimum_balance(account_size) + excess_lamports, + account_size as u64, + &token_program, + ), + initialize_ix, + ]; + + let tx = Transaction::new_signed_with_payer( + &instructions, + Some(&context.payer.pubkey()), + &[&context.payer, &multisig], + context.last_blockhash, + ); + context.banks_client.process_transaction(tx).await.unwrap(); + + let account = context + .banks_client + .get_account(multisig.pubkey()) + .await + .unwrap(); + + assert!(account.is_some()); + + let account = account.unwrap(); + assert_eq!( + account.lamports, + rent.minimum_balance(account_size) + excess_lamports + ); + + // When we try to withdraw the excess lamports with the wrong authority. + + let destination = Pubkey::new_unique(); + + let mut withdraw_ix = spl_token_2022::instruction::withdraw_excess_lamports( + &spl_token_2022::ID, + &multisig.pubkey(), + &destination, + &multisig.pubkey(), + &[&signer1_pubkey, &signer2_pubkey], + ) + .unwrap(); + // Switches the program id to the token program. + withdraw_ix.program_id = token_program; + + let tx = Transaction::new_signed_with_payer( + &[withdraw_ix], + Some(&context.payer.pubkey()), + &[&context.payer, &signer1, &signer2], + context.last_blockhash, + ); + let error = context + .banks_client + .process_transaction(tx) + .await + .unwrap_err(); + + // The we expect an error. + + assert_instruction_error!(error, InstructionError::MissingRequiredSignature); } From 2db12da6c4609a34694eb919ae3f02cdb5ff8cb4 Mon Sep 17 00:00:00 2001 From: febo Date: Mon, 10 Mar 2025 17:13:38 +0000 Subject: [PATCH 15/16] Fix merge --- Cargo.lock | 301 +++++++++++++++++++++- p-token/src/entrypoint.rs | 51 ++-- p-token/tests/withdraw_excess_lamports.rs | 2 - 3 files changed, 325 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3b7cd351..bcdc9550 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2846,7 +2846,7 @@ dependencies = [ "solana-program-test", "solana-sdk", "spl-token 4.0.2", - "spl-token-2022 7.0.0", + "spl-token-2022", "spl-token-interface", "test-case", ] @@ -5863,6 +5863,12 @@ dependencies = [ "solana-sdk-ids", ] +[[package]] +name = "solana-security-txt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "468aa43b7edb1f9b7b7b686d5c3aeb6630dc1708e86e31343499dd5c4d775183" + [[package]] name = "solana-seed-derivable" version = "2.2.1" @@ -6738,6 +6744,136 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spl-discriminator" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7398da23554a31660f17718164e31d31900956054f54f52d5ec1be51cb4f4b3" +dependencies = [ + "bytemuck", + "solana-program-error", + "solana-sha256-hasher", + "spl-discriminator-derive", +] + +[[package]] +name = "spl-discriminator-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750" +dependencies = [ + "quote", + "spl-discriminator-syn", + "syn 2.0.96", +] + +[[package]] +name = "spl-discriminator-syn" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f05593b7ca9eac7caca309720f2eafb96355e037e6d373b909a80fe7b69b9" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.8", + "syn 2.0.96", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-elgamal-registry" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce0f668975d2b0536e8a8fd60e56a05c467f06021dae037f1d0cfed0de2e231d" +dependencies = [ + "bytemuck", + "solana-program", + "solana-zk-sdk", + "spl-pod", + "spl-token-confidential-transfer-proof-extraction", +] + +[[package]] +name = "spl-memo" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f09647c0974e33366efeb83b8e2daebb329f0420149e74d3a4bd2c08cf9f7cb" +dependencies = [ + "solana-account-info", + "solana-instruction", + "solana-msg", + "solana-program-entrypoint", + "solana-program-error", + "solana-pubkey", +] + +[[package]] +name = "spl-pod" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a7d5950993e1ff2680bd989df298eeb169367fb2f9deeef1f132de6e4e8016" +dependencies = [ + "borsh 1.5.5", + "bytemuck", + "bytemuck_derive", + "num-derive", + "num-traits", + "solana-decode-error", + "solana-msg", + "solana-program-error", + "solana-program-option", + "solana-pubkey", + "solana-zk-sdk", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-program-error" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d39b5186f42b2b50168029d81e58e800b690877ef0b30580d107659250da1d1" +dependencies = [ + "num-derive", + "num-traits", + "solana-program", + "spl-program-error-derive", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-program-error-derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d375dd76c517836353e093c2dbb490938ff72821ab568b545fd30ab3256b3e" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.8", + "syn 2.0.96", +] + +[[package]] +name = "spl-tlv-account-resolution" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd99ff1e9ed2ab86e3fd582850d47a739fec1be9f4661cba1782d3a0f26805f3" +dependencies = [ + "bytemuck", + "num-derive", + "num-traits", + "solana-account-info", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-program-error", + "solana-pubkey", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-type-length-value", + "thiserror 1.0.69", +] + [[package]] name = "spl-token" version = "4.0.2" @@ -6786,6 +6922,105 @@ dependencies = [ "thiserror 2.0.11", ] +[[package]] +name = "spl-token" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed320a6c934128d4f7e54fe00e16b8aeaecf215799d060ae14f93378da6dc834" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "num_enum", + "solana-program", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-token-2022" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9048b26b0df0290f929ff91317c83db28b3ef99af2b3493dd35baa146774924c" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "num_enum", + "solana-program", + "solana-security-txt", + "solana-zk-sdk", + "spl-elgamal-registry", + "spl-memo", + "spl-pod", + "spl-token 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "spl-token-confidential-transfer-ciphertext-arithmetic", + "spl-token-confidential-transfer-proof-extraction", + "spl-token-confidential-transfer-proof-generation", + "spl-token-group-interface", + "spl-token-metadata-interface", + "spl-transfer-hook-interface", + "spl-type-length-value", + "thiserror 2.0.11", +] + +[[package]] +name = "spl-token-confidential-transfer-ciphertext-arithmetic" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170378693c5516090f6d37ae9bad2b9b6125069be68d9acd4865bbe9fc8499fd" +dependencies = [ + "base64 0.22.1", + "bytemuck", + "solana-curve25519", + "solana-zk-sdk", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-extraction" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff2d6a445a147c9d6dd77b8301b1e116c8299601794b558eafa409b342faf96" +dependencies = [ + "bytemuck", + "solana-curve25519", + "solana-program", + "solana-zk-sdk", + "spl-pod", + "thiserror 2.0.11", +] + +[[package]] +name = "spl-token-confidential-transfer-proof-generation" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e3597628b0d2fe94e7900fd17cdb4cfbb31ee35c66f82809d27d86e44b2848b" +dependencies = [ + "curve25519-dalek 4.1.3", + "solana-zk-sdk", + "thiserror 2.0.11", +] + +[[package]] +name = "spl-token-group-interface" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d595667ed72dbfed8c251708f406d7c2814a3fa6879893b323d56a10bedfc799" +dependencies = [ + "bytemuck", + "num-derive", + "num-traits", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-program-error", + "solana-pubkey", + "spl-discriminator", + "spl-pod", + "thiserror 1.0.69", +] + [[package]] name = "spl-token-interface" version = "0.0.0" @@ -6796,6 +7031,70 @@ dependencies = [ "strum_macros 0.27.1", ] +[[package]] +name = "spl-token-metadata-interface" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb9c89dbc877abd735f05547dcf9e6e12c00c11d6d74d8817506cab4c99fdbb" +dependencies = [ + "borsh 1.5.5", + "num-derive", + "num-traits", + "solana-borsh", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-program-error", + "solana-pubkey", + "spl-discriminator", + "spl-pod", + "spl-type-length-value", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-transfer-hook-interface" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa7503d52107c33c88e845e1351565050362c2314036ddf19a36cd25137c043" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "solana-account-info", + "solana-cpi", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-program-error", + "solana-pubkey", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-tlv-account-resolution", + "spl-type-length-value", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-type-length-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba70ef09b13af616a4c987797870122863cba03acc4284f226a4473b043923f9" +dependencies = [ + "bytemuck", + "num-derive", + "num-traits", + "solana-account-info", + "solana-decode-error", + "solana-msg", + "solana-program-error", + "spl-discriminator", + "spl-pod", + "thiserror 1.0.69", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/p-token/src/entrypoint.rs b/p-token/src/entrypoint.rs index 85965383..0296dd9d 100644 --- a/p-token/src/entrypoint.rs +++ b/p-token/src/entrypoint.rs @@ -2,7 +2,6 @@ use pinocchio::{ account_info::AccountInfo, default_panic_handler, no_allocator, program_entrypoint, program_error::ProgramError, pubkey::Pubkey, ProgramResult, }; -use spl_token_interface::instruction::TokenInstruction; use crate::processor::*; @@ -67,9 +66,9 @@ pub(crate) fn inner_process_instruction( return Err(ProgramError::InvalidInstructionData); }; - match instruction { + match *discriminator { // 0 - InitializeMint - TokenInstruction::InitializeMint => { + 0 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: InitializeMint"); @@ -83,21 +82,21 @@ pub(crate) fn inner_process_instruction( process_initialize_account(accounts) } // 3 - Transfer - TokenInstruction::Transfer => { + 3 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: Transfer"); process_transfer(accounts, instruction_data) } // 7 - MintTo - TokenInstruction::MintTo => { + 7 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: MintTo"); process_mint_to(accounts, instruction_data) } // 9 - CloseAccount - TokenInstruction::CloseAccount => { + 9 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: CloseAccount"); @@ -111,14 +110,14 @@ pub(crate) fn inner_process_instruction( process_initialize_account2(accounts, instruction_data) } // 18 - InitializeAccount3 - TokenInstruction::InitializeAccount3 => { + 18 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: InitializeAccount3"); process_initialize_account3(accounts, instruction_data) } // 20 - InitializeMint2 - TokenInstruction::InitializeMint2 => { + 20 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: InitializeMint2"); @@ -136,123 +135,123 @@ pub(crate) fn inner_process_instruction( fn inner_process_remaining_instruction( accounts: &[AccountInfo], instruction_data: &[u8], - instruction: TokenInstruction, + discriminator: u8, ) -> ProgramResult { match discriminator { // 2 - InitializeMultisig - TokenInstruction::InitializeMultisig => { + 2 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: InitializeMultisig"); process_initialize_multisig(accounts, instruction_data) } // 4 - Approve - TokenInstruction::Approve => { + 4 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: Approve"); process_approve(accounts, instruction_data) } // 5 - Revoke - TokenInstruction::Revoke => { + 5 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: Revoke"); process_revoke(accounts, instruction_data) } // 6 - SetAuthority - TokenInstruction::SetAuthority => { + 6 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: SetAuthority"); process_set_authority(accounts, instruction_data) } // 8 - Burn - TokenInstruction::Burn => { + 8 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: Burn"); process_burn(accounts, instruction_data) } // 10 - FreezeAccount - TokenInstruction::FreezeAccount => { + 10 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: FreezeAccount"); process_freeze_account(accounts) } // 11 - ThawAccount - TokenInstruction::ThawAccount => { + 11 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: ThawAccount"); process_thaw_account(accounts) } // 12 - TransferChecked - TokenInstruction::TransferChecked => { + 12 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: TransferChecked"); process_transfer_checked(accounts, instruction_data) } // 13 - ApproveChecked - TokenInstruction::ApproveChecked => { + 13 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: ApproveChecked"); process_approve_checked(accounts, instruction_data) } // 14 - MintToChecked - TokenInstruction::MintToChecked => { + 14 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: MintToChecked"); process_mint_to_checked(accounts, instruction_data) } // 15 - BurnChecked - TokenInstruction::BurnChecked => { + 15 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: BurnChecked"); process_burn_checked(accounts, instruction_data) } // 17 - SyncNative - TokenInstruction::SyncNative => { + 17 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: SyncNative"); process_sync_native(accounts) } // 19 - InitializeMultisig2 - TokenInstruction::InitializeMultisig2 => { + 19 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: InitializeMultisig2"); process_initialize_multisig2(accounts, instruction_data) } // 21 - GetAccountDataSize - TokenInstruction::GetAccountDataSize => { + 21 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: GetAccountDataSize"); process_get_account_data_size(accounts) } // 22 - InitializeImmutableOwner - TokenInstruction::InitializeImmutableOwner => { + 22 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: InitializeImmutableOwner"); process_initialize_immutable_owner(accounts) } // 23 - AmountToUiAmount - TokenInstruction::AmountToUiAmount => { + 23 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: AmountToUiAmount"); process_amount_to_ui_amount(accounts, instruction_data) } // 24 - UiAmountToAmount - TokenInstruction::UiAmountToAmount => { + 24 => { #[cfg(feature = "logging")] pinocchio::msg!("Instruction: UiAmountToAmount"); diff --git a/p-token/tests/withdraw_excess_lamports.rs b/p-token/tests/withdraw_excess_lamports.rs index 05bba6ba..f9bea087 100644 --- a/p-token/tests/withdraw_excess_lamports.rs +++ b/p-token/tests/withdraw_excess_lamports.rs @@ -1,5 +1,3 @@ -#![cfg(feature = "test-sbf")] - mod setup; use std::mem::size_of; From 43e8fceb065a964ccebba45d17a76934bd7d7af3 Mon Sep 17 00:00:00 2001 From: febo Date: Tue, 11 Mar 2025 14:58:32 +0000 Subject: [PATCH 16/16] Use assert_matches --- p-token/tests/setup/mod.rs | 43 ----------------------- p-token/tests/withdraw_excess_lamports.rs | 40 ++++++++++++++++----- 2 files changed, 32 insertions(+), 51 deletions(-) diff --git a/p-token/tests/setup/mod.rs b/p-token/tests/setup/mod.rs index 5871bfa8..c607de27 100644 --- a/p-token/tests/setup/mod.rs +++ b/p-token/tests/setup/mod.rs @@ -6,46 +6,3 @@ pub mod account; pub mod mint; pub const TOKEN_PROGRAM_ID: Pubkey = Pubkey::new_from_array(spl_token_interface::program::ID); - -#[macro_export] -macro_rules! assert_instruction_error { - ( $error:expr, $matcher:pat ) => { - match $error { - solana_program_test::BanksClientError::TransactionError( - solana_sdk::transaction::TransactionError::InstructionError(_, $matcher), - ) => { - assert!(true) - } - err => assert!(false, "Expected instruction error but got '{:#?}'", err), - }; - }; -} - -#[macro_export] -macro_rules! assert_custom_error { - ( $error:expr, $matcher:pat ) => { - match $error { - solana_program_test::BanksClientError::TransactionError( - solana_sdk::transaction::TransactionError::InstructionError( - _, - solana_sdk::instruction::InstructionError::Custom(x), - ), - ) => match num_traits::FromPrimitive::from_i32(x as i32) { - Some($matcher) => assert!(true), - Some(other) => { - assert!( - false, - "Expected another custom instruction error than '{:#?}'", - other - ) - } - None => assert!(false, "Expected custom instruction error"), - }, - err => assert!( - false, - "Expected custom instruction error but got '{:#?}'", - err - ), - }; - }; -} diff --git a/p-token/tests/withdraw_excess_lamports.rs b/p-token/tests/withdraw_excess_lamports.rs index f9bea087..6e56c0c4 100644 --- a/p-token/tests/withdraw_excess_lamports.rs +++ b/p-token/tests/withdraw_excess_lamports.rs @@ -1,17 +1,17 @@ mod setup; -use std::mem::size_of; - +use assert_matches::assert_matches; use setup::{mint, TOKEN_PROGRAM_ID}; -use solana_program_test::{tokio, ProgramTest}; +use solana_program_test::{tokio, BanksClientError, ProgramTest}; use solana_sdk::{ instruction::InstructionError, pubkey::Pubkey, signature::{Keypair, Signer}, system_instruction, - transaction::Transaction, + transaction::{Transaction, TransactionError}, }; use spl_token_interface::state::{account::Account, mint::Mint, multisig::Multisig}; +use std::mem::size_of; #[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")] #[tokio::test] @@ -417,7 +417,13 @@ async fn fail_withdraw_excess_lamports_from_mint_wrong_authority(token_program: // The we expect an error. - assert_custom_error!(error, spl_token::error::TokenError::OwnerMismatch); + assert_matches!( + error, + BanksClientError::TransactionError(TransactionError::InstructionError( + _, + InstructionError::Custom(4) // TokenError::OwnerMismatch + )) + ); } #[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")] @@ -527,7 +533,13 @@ async fn fail_withdraw_excess_lamports_from_account_wrong_authority(token_progra // The we expect an error. - assert_custom_error!(error, spl_token::error::TokenError::OwnerMismatch); + assert_matches!( + error, + BanksClientError::TransactionError(TransactionError::InstructionError( + _, + InstructionError::Custom(4) // TokenError::OwnerMismatch + )) + ); } #[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")] @@ -628,7 +640,13 @@ async fn fail_withdraw_excess_lamports_from_multisig_wrong_authority(token_progr // The we expect an error. - assert_custom_error!(error, spl_token::error::TokenError::OwnerMismatch); + assert_matches!( + error, + BanksClientError::TransactionError(TransactionError::InstructionError( + _, + InstructionError::Custom(4) // TokenError::OwnerMismatch + )) + ); } #[test_case::test_case(TOKEN_PROGRAM_ID ; "p-token")] @@ -728,5 +746,11 @@ async fn fail_withdraw_excess_lamports_from_multisig_missing_signer(token_progra // The we expect an error. - assert_instruction_error!(error, InstructionError::MissingRequiredSignature); + assert_matches!( + error, + BanksClientError::TransactionError(TransactionError::InstructionError( + _, + InstructionError::MissingRequiredSignature + )) + ); }