diff --git a/Cargo.lock b/Cargo.lock index 97104077..3f575cac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -736,18 +736,17 @@ dependencies = [ "anchor-spl", "bytemuck", "const-crypto", - "jupiter", "num", "num-traits", "num_enum", - "pinocchio", + "pinocchio 0.9.0", "pinocchio-token", "pinocchio-token-2022", "proptest", + "protocol-zap", "ruint", "spl-token-metadata-interface", "static_assertions", - "zap", ] [[package]] @@ -1113,9 +1112,9 @@ dependencies = [ [[package]] name = "jupiter" version = "0.1.0" +source = "git+https://github.com/MeteoraAg/zap-program?rev=064c58b317b9a85f212c0de72caea286fc72fdb4#064c58b317b9a85f212c0de72caea286fc72fdb4" dependencies = [ "anchor-lang", - "bytemuck", ] [[package]] @@ -1450,13 +1449,30 @@ name = "pinocchio" version = "0.9.0" source = "git+https://github.com/anza-xyz/pinocchio.git?rev=17b0e862c01a868ea07ef81a2f8a9b4a504bdfed#17b0e862c01a868ea07ef81a2f8a9b4a504bdfed" +[[package]] +name = "pinocchio" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b971851087bc3699b001954ad02389d50c41405ece3548cbcafc88b3e20017a" + +[[package]] +name = "pinocchio-pubkey" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0225638cadcbebae8932cb7f49cb5da7c15c21beb19f048f05a5ca7d93f065" +dependencies = [ + "five8_const", + "pinocchio 0.9.2", + "sha2-const-stable", +] + [[package]] name = "pinocchio-pubkey" version = "0.3.0" source = "git+https://github.com/anza-xyz/pinocchio.git?rev=17b0e862c01a868ea07ef81a2f8a9b4a504bdfed#17b0e862c01a868ea07ef81a2f8a9b4a504bdfed" dependencies = [ "five8_const", - "pinocchio", + "pinocchio 0.9.0", "sha2-const-stable", ] @@ -1465,8 +1481,8 @@ name = "pinocchio-token" version = "0.4.0" source = "git+https://github.com/anza-xyz/pinocchio.git?rev=17b0e862c01a868ea07ef81a2f8a9b4a504bdfed#17b0e862c01a868ea07ef81a2f8a9b4a504bdfed" dependencies = [ - "pinocchio", - "pinocchio-pubkey", + "pinocchio 0.9.0", + "pinocchio-pubkey 0.3.0 (git+https://github.com/anza-xyz/pinocchio.git?rev=17b0e862c01a868ea07ef81a2f8a9b4a504bdfed)", ] [[package]] @@ -1474,8 +1490,8 @@ name = "pinocchio-token-2022" version = "0.1.0" source = "git+https://github.com/anza-xyz/pinocchio.git?rev=17b0e862c01a868ea07ef81a2f8a9b4a504bdfed#17b0e862c01a868ea07ef81a2f8a9b4a504bdfed" dependencies = [ - "pinocchio", - "pinocchio-pubkey", + "pinocchio 0.9.0", + "pinocchio-pubkey 0.3.0 (git+https://github.com/anza-xyz/pinocchio.git?rev=17b0e862c01a868ea07ef81a2f8a9b4a504bdfed)", ] [[package]] @@ -1554,6 +1570,21 @@ dependencies = [ "unarray", ] +[[package]] +name = "protocol-zap" +version = "0.1.0" +source = "git+https://github.com/MeteoraAg/zap-program?rev=064c58b317b9a85f212c0de72caea286fc72fdb4#064c58b317b9a85f212c0de72caea286fc72fdb4" +dependencies = [ + "borsh 0.10.3", + "jupiter", + "num_enum", + "pinocchio 0.9.2", + "pinocchio-pubkey 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ruint", + "thiserror 2.0.12", + "zap-sdk", +] + [[package]] name = "qstring" version = "0.7.2" @@ -3687,11 +3718,11 @@ dependencies = [ ] [[package]] -name = "zap" +name = "zap-sdk" version = "0.1.0" +source = "git+https://github.com/MeteoraAg/zap-program?rev=064c58b317b9a85f212c0de72caea286fc72fdb4#064c58b317b9a85f212c0de72caea286fc72fdb4" dependencies = [ - "anchor-lang", - "bytemuck", + "solana-pubkey", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b4aa4273..6726bb65 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["programs/*", "rust-sdk", "libs/*"] +members = ["programs/*", "rust-sdk"] resolver = "2" [profile.release] diff --git a/idls/jupiter.json b/idls/jupiter.json deleted file mode 100644 index 9ea99c95..00000000 --- a/idls/jupiter.json +++ /dev/null @@ -1,2279 +0,0 @@ -{ - "address": "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4", - "metadata": { - "name": "jupiter", - "version": "0.1.0", - "spec": "0.1.0", - "address": "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4", - "description": "Jupiter aggregator program" - }, - "instructions": [ - { - "name": "claim", - "discriminator": [62, 198, 214, 193, 213, 159, 108, 210], - "accounts": [ - { - "name": "wallet", - "writable": true, - "address": "7JQeyNK55fkUPUmEotupBFpiBGpgEQYLe8Ht1VdSfxcP" - }, - { - "name": "program_authority", - "writable": true - }, - { - "name": "system_program", - "address": "11111111111111111111111111111111" - } - ], - "args": [ - { - "name": "id", - "type": "u8" - } - ], - "returns": "u64" - }, - { - "name": "claim_token", - "discriminator": [116, 206, 27, 191, 166, 19, 0, 73], - "accounts": [ - { - "name": "payer", - "writable": true, - "signer": true - }, - { - "name": "wallet", - "address": "7JQeyNK55fkUPUmEotupBFpiBGpgEQYLe8Ht1VdSfxcP" - }, - { - "name": "program_authority" - }, - { - "name": "program_token_account", - "writable": true - }, - { - "name": "destination_token_account", - "writable": true, - "pda": { - "seeds": [ - { - "kind": "account", - "path": "wallet" - }, - { - "kind": "account", - "path": "token_program" - }, - { - "kind": "account", - "path": "mint" - } - ], - "program": { - "kind": "const", - "value": [ - 140, 151, 37, 143, 78, 36, 137, 241, 187, 61, 16, 41, 20, 142, - 13, 131, 11, 90, 19, 153, 218, 255, 16, 132, 4, 142, 123, 216, - 219, 233, 248, 89 - ] - } - } - }, - { - "name": "mint" - }, - { - "name": "token_program" - }, - { - "name": "associated_token_program", - "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" - }, - { - "name": "system_program", - "address": "11111111111111111111111111111111" - } - ], - "args": [ - { - "name": "id", - "type": "u8" - } - ], - "returns": "u64" - }, - { - "name": "close_token", - "discriminator": [26, 74, 236, 151, 104, 64, 183, 249], - "accounts": [ - { - "name": "operator", - "signer": true, - "address": "9RAufBfjGQjDfrwxeyKmZWPADHSb8HcoqCdrmpqvCr1g" - }, - { - "name": "wallet", - "writable": true, - "address": "7JQeyNK55fkUPUmEotupBFpiBGpgEQYLe8Ht1VdSfxcP" - }, - { - "name": "program_authority" - }, - { - "name": "program_token_account", - "writable": true - }, - { - "name": "mint", - "writable": true - }, - { - "name": "token_program" - } - ], - "args": [ - { - "name": "id", - "type": "u8" - }, - { - "name": "burn_all", - "type": "bool" - } - ] - }, - { - "name": "create_token_ledger", - "discriminator": [232, 242, 197, 253, 240, 143, 129, 52], - "accounts": [ - { - "name": "token_ledger", - "writable": true, - "signer": true - }, - { - "name": "payer", - "writable": true, - "signer": true - }, - { - "name": "system_program", - "address": "11111111111111111111111111111111" - } - ], - "args": [] - }, - { - "name": "create_token_account", - "discriminator": [147, 241, 123, 100, 244, 132, 174, 118], - "accounts": [ - { - "name": "token_account", - "writable": true - }, - { - "name": "user", - "writable": true, - "signer": true - }, - { - "name": "mint" - }, - { - "name": "token_program" - }, - { - "name": "system_program", - "address": "11111111111111111111111111111111" - } - ], - "args": [ - { - "name": "bump", - "type": "u8" - } - ] - }, - { - "name": "exact_out_route", - "discriminator": [208, 51, 239, 151, 123, 43, 237, 92], - "accounts": [ - { - "name": "token_program" - }, - { - "name": "user_transfer_authority", - "signer": true - }, - { - "name": "user_source_token_account", - "writable": true - }, - { - "name": "user_destination_token_account", - "writable": true - }, - { - "name": "destination_token_account", - "writable": true, - "optional": true - }, - { - "name": "source_mint" - }, - { - "name": "destination_mint" - }, - { - "name": "platform_fee_account", - "writable": true, - "optional": true - }, - { - "name": "token_2022_program", - "optional": true - }, - { - "name": "event_authority", - "address": "D8cy77BBepLMngZx6ZukaTff5hCt1HrWyKk3Hnd9oitf" - }, - { - "name": "program" - } - ], - "args": [ - { - "name": "route_plan", - "type": { - "vec": { - "defined": { - "name": "RoutePlanStep" - } - } - } - }, - { - "name": "out_amount", - "type": "u64" - }, - { - "name": "quoted_in_amount", - "type": "u64" - }, - { - "name": "slippage_bps", - "type": "u16" - }, - { - "name": "platform_fee_bps", - "type": "u8" - } - ], - "returns": "u64" - }, - { - "name": "route", - "discriminator": [229, 23, 203, 151, 122, 227, 173, 42], - "accounts": [ - { - "name": "token_program" - }, - { - "name": "user_transfer_authority", - "signer": true - }, - { - "name": "user_source_token_account", - "writable": true - }, - { - "name": "user_destination_token_account", - "writable": true - }, - { - "name": "destination_token_account", - "writable": true, - "optional": true - }, - { - "name": "destination_mint" - }, - { - "name": "platform_fee_account", - "writable": true, - "optional": true - }, - { - "name": "event_authority", - "address": "D8cy77BBepLMngZx6ZukaTff5hCt1HrWyKk3Hnd9oitf" - }, - { - "name": "program" - } - ], - "args": [ - { - "name": "route_plan", - "type": { - "vec": { - "defined": { - "name": "RoutePlanStep" - } - } - } - }, - { - "name": "in_amount", - "type": "u64" - }, - { - "name": "quoted_out_amount", - "type": "u64" - }, - { - "name": "slippage_bps", - "type": "u16" - }, - { - "name": "platform_fee_bps", - "type": "u8" - } - ], - "returns": "u64" - }, - { - "name": "route_with_token_ledger", - "discriminator": [150, 86, 71, 116, 167, 93, 14, 104], - "accounts": [ - { - "name": "token_program" - }, - { - "name": "user_transfer_authority", - "signer": true - }, - { - "name": "user_source_token_account", - "writable": true - }, - { - "name": "user_destination_token_account", - "writable": true - }, - { - "name": "destination_token_account", - "writable": true, - "optional": true - }, - { - "name": "destination_mint" - }, - { - "name": "platform_fee_account", - "writable": true, - "optional": true - }, - { - "name": "token_ledger" - }, - { - "name": "event_authority", - "address": "D8cy77BBepLMngZx6ZukaTff5hCt1HrWyKk3Hnd9oitf" - }, - { - "name": "program" - } - ], - "args": [ - { - "name": "route_plan", - "type": { - "vec": { - "defined": { - "name": "RoutePlanStep" - } - } - } - }, - { - "name": "quoted_out_amount", - "type": "u64" - }, - { - "name": "slippage_bps", - "type": "u16" - }, - { - "name": "platform_fee_bps", - "type": "u8" - } - ], - "returns": "u64" - }, - { - "name": "set_token_ledger", - "discriminator": [228, 85, 185, 112, 78, 79, 77, 2], - "accounts": [ - { - "name": "token_ledger", - "writable": true - }, - { - "name": "token_account" - } - ], - "args": [] - }, - { - "name": "shared_accounts_exact_out_route", - "discriminator": [176, 209, 105, 168, 154, 125, 69, 62], - "accounts": [ - { - "name": "token_program" - }, - { - "name": "program_authority" - }, - { - "name": "user_transfer_authority", - "signer": true - }, - { - "name": "source_token_account", - "writable": true - }, - { - "name": "program_source_token_account", - "writable": true - }, - { - "name": "program_destination_token_account", - "writable": true - }, - { - "name": "destination_token_account", - "writable": true - }, - { - "name": "source_mint" - }, - { - "name": "destination_mint" - }, - { - "name": "platform_fee_account", - "writable": true, - "optional": true - }, - { - "name": "token_2022_program", - "optional": true - }, - { - "name": "event_authority", - "address": "D8cy77BBepLMngZx6ZukaTff5hCt1HrWyKk3Hnd9oitf" - }, - { - "name": "program" - } - ], - "args": [ - { - "name": "id", - "type": "u8" - }, - { - "name": "route_plan", - "type": { - "vec": { - "defined": { - "name": "RoutePlanStep" - } - } - } - }, - { - "name": "out_amount", - "type": "u64" - }, - { - "name": "quoted_in_amount", - "type": "u64" - }, - { - "name": "slippage_bps", - "type": "u16" - }, - { - "name": "platform_fee_bps", - "type": "u8" - } - ], - "returns": "u64" - }, - { - "name": "shared_accounts_route", - "discriminator": [193, 32, 155, 51, 65, 214, 156, 129], - "accounts": [ - { - "name": "token_program" - }, - { - "name": "program_authority" - }, - { - "name": "user_transfer_authority", - "signer": true - }, - { - "name": "source_token_account", - "writable": true - }, - { - "name": "program_source_token_account", - "writable": true - }, - { - "name": "program_destination_token_account", - "writable": true - }, - { - "name": "destination_token_account", - "writable": true - }, - { - "name": "source_mint" - }, - { - "name": "destination_mint" - }, - { - "name": "platform_fee_account", - "writable": true, - "optional": true - }, - { - "name": "token_2022_program", - "optional": true - }, - { - "name": "event_authority", - "address": "D8cy77BBepLMngZx6ZukaTff5hCt1HrWyKk3Hnd9oitf" - }, - { - "name": "program" - } - ], - "args": [ - { - "name": "id", - "type": "u8" - }, - { - "name": "route_plan", - "type": { - "vec": { - "defined": { - "name": "RoutePlanStep" - } - } - } - }, - { - "name": "in_amount", - "type": "u64" - }, - { - "name": "quoted_out_amount", - "type": "u64" - }, - { - "name": "slippage_bps", - "type": "u16" - }, - { - "name": "platform_fee_bps", - "type": "u8" - } - ], - "returns": "u64" - }, - { - "name": "shared_accounts_route_with_token_ledger", - "discriminator": [230, 121, 143, 80, 119, 159, 106, 170], - "accounts": [ - { - "name": "token_program" - }, - { - "name": "program_authority" - }, - { - "name": "user_transfer_authority", - "signer": true - }, - { - "name": "source_token_account", - "writable": true - }, - { - "name": "program_source_token_account", - "writable": true - }, - { - "name": "program_destination_token_account", - "writable": true - }, - { - "name": "destination_token_account", - "writable": true - }, - { - "name": "source_mint" - }, - { - "name": "destination_mint" - }, - { - "name": "platform_fee_account", - "writable": true, - "optional": true - }, - { - "name": "token_2022_program", - "optional": true - }, - { - "name": "token_ledger" - }, - { - "name": "event_authority", - "address": "D8cy77BBepLMngZx6ZukaTff5hCt1HrWyKk3Hnd9oitf" - }, - { - "name": "program" - } - ], - "args": [ - { - "name": "id", - "type": "u8" - }, - { - "name": "route_plan", - "type": { - "vec": { - "defined": { - "name": "RoutePlanStep" - } - } - } - }, - { - "name": "quoted_out_amount", - "type": "u64" - }, - { - "name": "slippage_bps", - "type": "u16" - }, - { - "name": "platform_fee_bps", - "type": "u8" - } - ], - "returns": "u64" - }, - { - "name": "exact_out_route_v2", - "discriminator": [157, 138, 184, 82, 21, 244, 243, 36], - "accounts": [ - { - "name": "user_transfer_authority", - "signer": true - }, - { - "name": "user_source_token_account", - "writable": true - }, - { - "name": "user_destination_token_account", - "writable": true - }, - { - "name": "source_mint" - }, - { - "name": "destination_mint" - }, - { - "name": "source_token_program" - }, - { - "name": "destination_token_program" - }, - { - "name": "destination_token_account", - "writable": true, - "optional": true - }, - { - "name": "event_authority", - "address": "D8cy77BBepLMngZx6ZukaTff5hCt1HrWyKk3Hnd9oitf" - }, - { - "name": "program" - } - ], - "args": [ - { - "name": "out_amount", - "type": "u64" - }, - { - "name": "quoted_in_amount", - "type": "u64" - }, - { - "name": "slippage_bps", - "type": "u16" - }, - { - "name": "platform_fee_bps", - "type": "u16" - }, - { - "name": "positive_slippage_bps", - "type": "u16" - }, - { - "name": "route_plan", - "type": { - "vec": { - "defined": { - "name": "RoutePlanStepV2" - } - } - } - } - ], - "returns": "u64" - }, - { - "name": "route_v2", - "discriminator": [187, 100, 250, 204, 49, 196, 175, 20], - "accounts": [ - { - "name": "user_transfer_authority", - "signer": true - }, - { - "name": "user_source_token_account", - "writable": true - }, - { - "name": "user_destination_token_account", - "writable": true - }, - { - "name": "source_mint" - }, - { - "name": "destination_mint" - }, - { - "name": "source_token_program" - }, - { - "name": "destination_token_program" - }, - { - "name": "destination_token_account", - "writable": true, - "optional": true - }, - { - "name": "event_authority", - "address": "D8cy77BBepLMngZx6ZukaTff5hCt1HrWyKk3Hnd9oitf" - }, - { - "name": "program" - } - ], - "args": [ - { - "name": "in_amount", - "type": "u64" - }, - { - "name": "quoted_out_amount", - "type": "u64" - }, - { - "name": "slippage_bps", - "type": "u16" - }, - { - "name": "platform_fee_bps", - "type": "u16" - }, - { - "name": "positive_slippage_bps", - "type": "u16" - }, - { - "name": "route_plan", - "type": { - "vec": { - "defined": { - "name": "RoutePlanStepV2" - } - } - } - } - ], - "returns": "u64" - }, - { - "name": "shared_accounts_exact_out_route_v2", - "discriminator": [53, 96, 229, 202, 216, 187, 250, 24], - "accounts": [ - { - "name": "program_authority" - }, - { - "name": "user_transfer_authority", - "signer": true - }, - { - "name": "source_token_account", - "writable": true - }, - { - "name": "program_source_token_account", - "writable": true - }, - { - "name": "program_destination_token_account", - "writable": true - }, - { - "name": "destination_token_account", - "writable": true - }, - { - "name": "source_mint" - }, - { - "name": "destination_mint" - }, - { - "name": "source_token_program" - }, - { - "name": "destination_token_program" - }, - { - "name": "event_authority", - "address": "D8cy77BBepLMngZx6ZukaTff5hCt1HrWyKk3Hnd9oitf" - }, - { - "name": "program" - } - ], - "args": [ - { - "name": "id", - "type": "u8" - }, - { - "name": "out_amount", - "type": "u64" - }, - { - "name": "quoted_in_amount", - "type": "u64" - }, - { - "name": "slippage_bps", - "type": "u16" - }, - { - "name": "platform_fee_bps", - "type": "u16" - }, - { - "name": "positive_slippage_bps", - "type": "u16" - }, - { - "name": "route_plan", - "type": { - "vec": { - "defined": { - "name": "RoutePlanStepV2" - } - } - } - } - ], - "returns": "u64" - }, - { - "name": "shared_accounts_route_v2", - "discriminator": [209, 152, 83, 147, 124, 254, 216, 233], - "accounts": [ - { - "name": "program_authority" - }, - { - "name": "user_transfer_authority", - "signer": true - }, - { - "name": "source_token_account", - "writable": true - }, - { - "name": "program_source_token_account", - "writable": true - }, - { - "name": "program_destination_token_account", - "writable": true - }, - { - "name": "destination_token_account", - "writable": true - }, - { - "name": "source_mint" - }, - { - "name": "destination_mint" - }, - { - "name": "source_token_program" - }, - { - "name": "destination_token_program" - }, - { - "name": "event_authority", - "address": "D8cy77BBepLMngZx6ZukaTff5hCt1HrWyKk3Hnd9oitf" - }, - { - "name": "program" - } - ], - "args": [ - { - "name": "id", - "type": "u8" - }, - { - "name": "in_amount", - "type": "u64" - }, - { - "name": "quoted_out_amount", - "type": "u64" - }, - { - "name": "slippage_bps", - "type": "u16" - }, - { - "name": "platform_fee_bps", - "type": "u16" - }, - { - "name": "positive_slippage_bps", - "type": "u16" - }, - { - "name": "route_plan", - "type": { - "vec": { - "defined": { - "name": "RoutePlanStepV2" - } - } - } - } - ], - "returns": "u64" - } - ], - "accounts": [ - { - "name": "TokenLedger", - "discriminator": [156, 247, 9, 188, 54, 108, 85, 77] - } - ], - "events": [ - { - "name": "FeeEvent", - "discriminator": [73, 79, 78, 127, 184, 213, 13, 220] - }, - { - "name": "SwapEvent", - "discriminator": [64, 198, 205, 232, 38, 8, 113, 226] - }, - { - "name": "SwapsEvent", - "discriminator": [152, 47, 78, 235, 192, 96, 110, 106] - }, - { - "name": "CandidateSwapResults", - "discriminator": [45, 9, 244, 30, 229, 52, 168, 123] - }, - { - "name": "BestSwapOutAmountViolation", - "discriminator": [124, 66, 196, 51, 218, 173, 46, 93] - } - ], - "errors": [ - { - "code": 6000, - "name": "EmptyRoute", - "msg": "Empty route" - }, - { - "code": 6001, - "name": "SlippageToleranceExceeded", - "msg": "Slippage tolerance exceeded" - }, - { - "code": 6002, - "name": "InvalidCalculation", - "msg": "Invalid calculation" - }, - { - "code": 6003, - "name": "MissingPlatformFeeAccount", - "msg": "Missing platform fee account" - }, - { - "code": 6004, - "name": "InvalidSlippage", - "msg": "Invalid slippage" - }, - { - "code": 6005, - "name": "NotEnoughPercent", - "msg": "Not enough percent to 100" - }, - { - "code": 6006, - "name": "InvalidInputIndex", - "msg": "Token input index is invalid" - }, - { - "code": 6007, - "name": "InvalidOutputIndex", - "msg": "Token output index is invalid" - }, - { - "code": 6008, - "name": "NotEnoughAccountKeys", - "msg": "Not Enough Account keys" - }, - { - "code": 6009, - "name": "NonZeroMinimumOutAmountNotSupported", - "msg": "Non zero minimum out amount not supported" - }, - { - "code": 6010, - "name": "InvalidRoutePlan", - "msg": "Invalid route plan" - }, - { - "code": 6011, - "name": "InvalidReferralAuthority", - "msg": "Invalid referral authority" - }, - { - "code": 6012, - "name": "LedgerTokenAccountDoesNotMatch", - "msg": "Token account doesn't match the ledger" - }, - { - "code": 6013, - "name": "InvalidTokenLedger", - "msg": "Invalid token ledger" - }, - { - "code": 6014, - "name": "IncorrectTokenProgramID", - "msg": "Token program ID is invalid" - }, - { - "code": 6015, - "name": "TokenProgramNotProvided", - "msg": "Token program not provided" - }, - { - "code": 6016, - "name": "SwapNotSupported", - "msg": "Swap not supported" - }, - { - "code": 6017, - "name": "ExactOutAmountNotMatched", - "msg": "Exact out amount doesn't match" - }, - { - "code": 6018, - "name": "SourceAndDestinationMintCannotBeTheSame", - "msg": "Source mint and destination mint cannot the same" - }, - { - "code": 6019, - "name": "InvalidMint", - "msg": "Invalid mint" - }, - { - "code": 6020, - "name": "InvalidProgramAuthority", - "msg": "Invalid program authority" - }, - { - "code": 6021, - "name": "InvalidOutputTokenAccount", - "msg": "Invalid output token account" - }, - { - "code": 6022, - "name": "InvalidFeeWallet", - "msg": "Invalid fee wallet" - }, - { - "code": 6023, - "name": "InvalidAuthority", - "msg": "Invalid authority" - }, - { - "code": 6024, - "name": "InsufficientFunds", - "msg": "Insufficient funds" - }, - { - "code": 6025, - "name": "InvalidTokenAccount", - "msg": "Invalid token account" - }, - { - "code": 6026, - "name": "BondingCurveAlreadyCompleted", - "msg": "Bonding curve already completed" - } - ], - "types": [ - { - "name": "FeeEvent", - "type": { - "kind": "struct", - "fields": [ - { - "name": "account", - "type": "pubkey" - }, - { - "name": "mint", - "type": "pubkey" - }, - { - "name": "amount", - "type": "u64" - } - ] - } - }, - { - "name": "RemainingAccountsInfo", - "type": { - "kind": "struct", - "fields": [ - { - "name": "slices", - "type": { - "vec": { - "defined": { - "name": "RemainingAccountsSlice" - } - } - } - } - ] - } - }, - { - "name": "RemainingAccountsSlice", - "type": { - "kind": "struct", - "fields": [ - { - "name": "accounts_type", - "type": "u8" - }, - { - "name": "length", - "type": "u8" - } - ] - } - }, - { - "name": "AccountsType", - "type": { - "kind": "enum", - "variants": [ - { - "name": "TransferHookA" - }, - { - "name": "TransferHookB" - }, - { - "name": "TransferHookReward" - }, - { - "name": "TransferHookInput" - }, - { - "name": "TransferHookIntermediate" - }, - { - "name": "TransferHookOutput" - }, - { - "name": "SupplementalTickArrays" - }, - { - "name": "SupplementalTickArraysOne" - }, - { - "name": "SupplementalTickArraysTwo" - } - ] - } - }, - { - "name": "DefiTunaAccountsType", - "type": { - "kind": "enum", - "variants": [ - { - "name": "TransferHookA" - }, - { - "name": "TransferHookB" - }, - { - "name": "TransferHookInput" - }, - { - "name": "TransferHookIntermediate" - }, - { - "name": "TransferHookOutput" - }, - { - "name": "SupplementalTickArrays" - }, - { - "name": "SupplementalTickArraysOne" - }, - { - "name": "SupplementalTickArraysTwo" - } - ] - } - }, - { - "name": "RoutePlanStep", - "type": { - "kind": "struct", - "fields": [ - { - "name": "swap", - "type": { - "defined": { - "name": "Swap" - } - } - }, - { - "name": "percent", - "type": "u8" - }, - { - "name": "input_index", - "type": "u8" - }, - { - "name": "output_index", - "type": "u8" - } - ] - } - }, - { - "name": "RoutePlanStepV2", - "type": { - "kind": "struct", - "fields": [ - { - "name": "swap", - "type": { - "defined": { - "name": "Swap" - } - } - }, - { - "name": "bps", - "type": "u16" - }, - { - "name": "input_index", - "type": "u8" - }, - { - "name": "output_index", - "type": "u8" - } - ] - } - }, - { - "name": "Side", - "type": { - "kind": "enum", - "variants": [ - { - "name": "Bid" - }, - { - "name": "Ask" - } - ] - } - }, - { - "name": "Swap", - "type": { - "kind": "enum", - "variants": [ - { - "name": "Saber" - }, - { - "name": "SaberAddDecimalsDeposit" - }, - { - "name": "SaberAddDecimalsWithdraw" - }, - { - "name": "TokenSwap" - }, - { - "name": "Sencha" - }, - { - "name": "Step" - }, - { - "name": "Cropper" - }, - { - "name": "Raydium" - }, - { - "name": "Crema", - "fields": [ - { - "name": "a_to_b", - "type": "bool" - } - ] - }, - { - "name": "Lifinity" - }, - { - "name": "Mercurial" - }, - { - "name": "Cykura" - }, - { - "name": "Serum", - "fields": [ - { - "name": "side", - "type": { - "defined": { - "name": "Side" - } - } - } - ] - }, - { - "name": "MarinadeDeposit" - }, - { - "name": "MarinadeUnstake" - }, - { - "name": "Aldrin", - "fields": [ - { - "name": "side", - "type": { - "defined": { - "name": "Side" - } - } - } - ] - }, - { - "name": "AldrinV2", - "fields": [ - { - "name": "side", - "type": { - "defined": { - "name": "Side" - } - } - } - ] - }, - { - "name": "Whirlpool", - "fields": [ - { - "name": "a_to_b", - "type": "bool" - } - ] - }, - { - "name": "Invariant", - "fields": [ - { - "name": "x_to_y", - "type": "bool" - } - ] - }, - { - "name": "Meteora" - }, - { - "name": "GooseFX" - }, - { - "name": "DeltaFi", - "fields": [ - { - "name": "stable", - "type": "bool" - } - ] - }, - { - "name": "Balansol" - }, - { - "name": "MarcoPolo", - "fields": [ - { - "name": "x_to_y", - "type": "bool" - } - ] - }, - { - "name": "Dradex", - "fields": [ - { - "name": "side", - "type": { - "defined": { - "name": "Side" - } - } - } - ] - }, - { - "name": "LifinityV2" - }, - { - "name": "RaydiumClmm" - }, - { - "name": "Openbook", - "fields": [ - { - "name": "side", - "type": { - "defined": { - "name": "Side" - } - } - } - ] - }, - { - "name": "Phoenix", - "fields": [ - { - "name": "side", - "type": { - "defined": { - "name": "Side" - } - } - } - ] - }, - { - "name": "Symmetry", - "fields": [ - { - "name": "from_token_id", - "type": "u64" - }, - { - "name": "to_token_id", - "type": "u64" - } - ] - }, - { - "name": "TokenSwapV2" - }, - { - "name": "HeliumTreasuryManagementRedeemV0" - }, - { - "name": "StakeDexStakeWrappedSol" - }, - { - "name": "StakeDexSwapViaStake", - "fields": [ - { - "name": "bridge_stake_seed", - "type": "u32" - } - ] - }, - { - "name": "GooseFXV2" - }, - { - "name": "Perps" - }, - { - "name": "PerpsAddLiquidity" - }, - { - "name": "PerpsRemoveLiquidity" - }, - { - "name": "MeteoraDlmm" - }, - { - "name": "OpenBookV2", - "fields": [ - { - "name": "side", - "type": { - "defined": { - "name": "Side" - } - } - } - ] - }, - { - "name": "RaydiumClmmV2" - }, - { - "name": "StakeDexPrefundWithdrawStakeAndDepositStake", - "fields": [ - { - "name": "bridge_stake_seed", - "type": "u32" - } - ] - }, - { - "name": "Clone", - "fields": [ - { - "name": "pool_index", - "type": "u8" - }, - { - "name": "quantity_is_input", - "type": "bool" - }, - { - "name": "quantity_is_collateral", - "type": "bool" - } - ] - }, - { - "name": "SanctumS", - "fields": [ - { - "name": "src_lst_value_calc_accs", - "type": "u8" - }, - { - "name": "dst_lst_value_calc_accs", - "type": "u8" - }, - { - "name": "src_lst_index", - "type": "u32" - }, - { - "name": "dst_lst_index", - "type": "u32" - } - ] - }, - { - "name": "SanctumSAddLiquidity", - "fields": [ - { - "name": "lst_value_calc_accs", - "type": "u8" - }, - { - "name": "lst_index", - "type": "u32" - } - ] - }, - { - "name": "SanctumSRemoveLiquidity", - "fields": [ - { - "name": "lst_value_calc_accs", - "type": "u8" - }, - { - "name": "lst_index", - "type": "u32" - } - ] - }, - { - "name": "RaydiumCP" - }, - { - "name": "WhirlpoolSwapV2", - "fields": [ - { - "name": "a_to_b", - "type": "bool" - }, - { - "name": "remaining_accounts_info", - "type": { - "option": { - "defined": { - "name": "RemainingAccountsInfo" - } - } - } - } - ] - }, - { - "name": "OneIntro" - }, - { - "name": "PumpWrappedBuy" - }, - { - "name": "PumpWrappedSell" - }, - { - "name": "PerpsV2" - }, - { - "name": "PerpsV2AddLiquidity" - }, - { - "name": "PerpsV2RemoveLiquidity" - }, - { - "name": "MoonshotWrappedBuy" - }, - { - "name": "MoonshotWrappedSell" - }, - { - "name": "StabbleStableSwap" - }, - { - "name": "StabbleWeightedSwap" - }, - { - "name": "Obric", - "fields": [ - { - "name": "x_to_y", - "type": "bool" - } - ] - }, - { - "name": "FoxBuyFromEstimatedCost" - }, - { - "name": "FoxClaimPartial", - "fields": [ - { - "name": "is_y", - "type": "bool" - } - ] - }, - { - "name": "SolFi", - "fields": [ - { - "name": "is_quote_to_base", - "type": "bool" - } - ] - }, - { - "name": "SolayerDelegateNoInit" - }, - { - "name": "SolayerUndelegateNoInit" - }, - { - "name": "TokenMill", - "fields": [ - { - "name": "side", - "type": { - "defined": { - "name": "Side" - } - } - } - ] - }, - { - "name": "DaosFunBuy" - }, - { - "name": "DaosFunSell" - }, - { - "name": "ZeroFi" - }, - { - "name": "StakeDexWithdrawWrappedSol" - }, - { - "name": "VirtualsBuy" - }, - { - "name": "VirtualsSell" - }, - { - "name": "Perena", - "fields": [ - { - "name": "in_index", - "type": "u8" - }, - { - "name": "out_index", - "type": "u8" - } - ] - }, - { - "name": "PumpSwapBuy" - }, - { - "name": "PumpSwapSell" - }, - { - "name": "Gamma" - }, - { - "name": "MeteoraDlmmSwapV2", - "fields": [ - { - "name": "remaining_accounts_info", - "type": { - "defined": { - "name": "RemainingAccountsInfo" - } - } - } - ] - }, - { - "name": "Woofi" - }, - { - "name": "MeteoraDammV2" - }, - { - "name": "MeteoraDynamicBondingCurveSwap" - }, - { - "name": "StabbleStableSwapV2" - }, - { - "name": "StabbleWeightedSwapV2" - }, - { - "name": "RaydiumLaunchlabBuy", - "fields": [ - { - "name": "share_fee_rate", - "type": "u64" - } - ] - }, - { - "name": "RaydiumLaunchlabSell", - "fields": [ - { - "name": "share_fee_rate", - "type": "u64" - } - ] - }, - { - "name": "BoopdotfunWrappedBuy" - }, - { - "name": "BoopdotfunWrappedSell" - }, - { - "name": "Plasma", - "fields": [ - { - "name": "side", - "type": { - "defined": { - "name": "Side" - } - } - } - ] - }, - { - "name": "GoonFi", - "fields": [ - { - "name": "is_bid", - "type": "bool" - }, - { - "name": "blacklist_bump", - "type": "u8" - } - ] - }, - { - "name": "HumidiFi", - "fields": [ - { - "name": "swap_id", - "type": "u64" - }, - { - "name": "is_base_to_quote", - "type": "bool" - } - ] - }, - { - "name": "MeteoraDynamicBondingCurveSwapWithRemainingAccounts" - }, - { - "name": "TesseraV", - "fields": [ - { - "name": "side", - "type": { - "defined": { - "name": "Side" - } - } - } - ] - }, - { - "name": "PumpWrappedBuyV2" - }, - { - "name": "PumpWrappedSellV2" - }, - { - "name": "PumpSwapBuyV2" - }, - { - "name": "PumpSwapSellV2" - }, - { - "name": "Heaven", - "fields": [ - { - "name": "a_to_b", - "type": "bool" - } - ] - }, - { - "name": "SolFiV2", - "fields": [ - { - "name": "is_quote_to_base", - "type": "bool" - } - ] - }, - { - "name": "Aquifer" - }, - { - "name": "PumpWrappedBuyV3" - }, - { - "name": "PumpWrappedSellV3" - }, - { - "name": "PumpSwapBuyV3" - }, - { - "name": "PumpSwapSellV3" - }, - { - "name": "JupiterLendDeposit" - }, - { - "name": "JupiterLendRedeem" - }, - { - "name": "DefiTuna", - "fields": [ - { - "name": "a_to_b", - "type": "bool" - }, - { - "name": "remaining_accounts_info", - "type": { - "option": { - "defined": { - "name": "RemainingAccountsInfo" - } - } - } - } - ] - }, - { - "name": "AlphaQ", - "fields": [ - { - "name": "a_to_b", - "type": "bool" - } - ] - }, - { - "name": "RaydiumV2" - }, - { - "name": "SarosDlmm", - "fields": [ - { - "name": "swap_for_y", - "type": "bool" - } - ] - }, - { - "name": "Futarchy", - "fields": [ - { - "name": "side", - "type": { - "defined": { - "name": "Side" - } - } - } - ] - }, - { - "name": "MeteoraDammV2WithRemainingAccounts" - }, - { - "name": "Obsidian" - }, - { - "name": "WhaleStreet", - "fields": [ - { - "name": "side", - "type": { - "defined": { - "name": "Side" - } - } - } - ] - }, - { - "name": "DynamicV1", - "fields": [ - { - "name": "candidate_swaps", - "type": { - "vec": { - "defined": { - "name": "CandidateSwap" - } - } - } - } - ] - }, - { - "name": "PumpWrappedBuyV4" - }, - { - "name": "PumpWrappedSellV4" - }, - { - "name": "CarrotIssue" - }, - { - "name": "CarrotRedeem" - }, - { - "name": "Manifest", - "fields": [ - { - "name": "side", - "type": { - "defined": { - "name": "Side" - } - } - } - ] - }, - { - "name": "BisonFi", - "fields": [ - { - "name": "a_to_b", - "type": "bool" - } - ] - } - ] - } - }, - { - "name": "CandidateSwap", - "type": { - "kind": "enum", - "variants": [ - { - "name": "HumidiFi", - "fields": [ - { - "name": "swap_id", - "type": "u64" - }, - { - "name": "is_base_to_quote", - "type": "bool" - } - ] - }, - { - "name": "TesseraV", - "fields": [ - { - "name": "side", - "type": { - "defined": { - "name": "Side" - } - } - } - ] - } - ] - } - }, - { - "name": "SwapEvent", - "type": { - "kind": "struct", - "fields": [ - { - "name": "amm", - "type": "pubkey" - }, - { - "name": "input_mint", - "type": "pubkey" - }, - { - "name": "input_amount", - "type": "u64" - }, - { - "name": "output_mint", - "type": "pubkey" - }, - { - "name": "output_amount", - "type": "u64" - } - ] - } - }, - { - "name": "SwapEventV2", - "type": { - "kind": "struct", - "fields": [ - { - "name": "input_mint", - "type": "pubkey" - }, - { - "name": "input_amount", - "type": "u64" - }, - { - "name": "output_mint", - "type": "pubkey" - }, - { - "name": "output_amount", - "type": "u64" - } - ] - } - }, - { - "name": "SwapsEvent", - "type": { - "kind": "struct", - "fields": [ - { - "name": "swap_events", - "type": { - "vec": { - "defined": { - "name": "SwapEventV2" - } - } - } - } - ] - } - }, - { - "name": "TokenLedger", - "type": { - "kind": "struct", - "fields": [ - { - "name": "token_account", - "type": "pubkey" - }, - { - "name": "amount", - "type": "u64" - } - ] - } - }, - { - "name": "BestSwapOutAmountViolation", - "type": { - "kind": "struct", - "fields": [ - { - "name": "expected_out_amount", - "type": "u64" - }, - { - "name": "out_amount", - "type": "u64" - } - ] - } - }, - { - "name": "CandidateSwapResult", - "type": { - "kind": "enum", - "variants": [ - { - "name": "OutAmount", - "fields": ["u64"] - }, - { - "name": "ProgramError", - "fields": ["u64"] - } - ] - } - }, - { - "name": "CandidateSwapResults", - "type": { - "kind": "struct", - "fields": [ - { - "name": "results", - "type": { - "vec": { - "defined": { - "name": "CandidateSwapResult" - } - } - } - } - ] - } - } - ] -} diff --git a/idls/zap.json b/idls/zap.json deleted file mode 100644 index 880e7bf0..00000000 --- a/idls/zap.json +++ /dev/null @@ -1,390 +0,0 @@ -{ - "address": "zapvX9M3uf5pvy4wRPAbQgdQsM1xmuiFnkfHKPvwMiz", - "metadata": { - "name": "zap", - "version": "0.2.0", - "spec": "0.1.0", - "description": "Created with Anchor" - }, - "instructions": [ - { - "name": "close_ledger_account", - "discriminator": [189, 122, 172, 13, 122, 54, 54, 51], - "accounts": [ - { - "name": "ledger", - "writable": true - }, - { - "name": "owner", - "signer": true, - "relations": ["ledger"] - }, - { - "name": "rent_receiver", - "writable": true, - "signer": true - } - ], - "args": [] - }, - { - "name": "initialize_ledger_account", - "discriminator": [120, 69, 30, 74, 76, 242, 153, 162], - "accounts": [ - { - "name": "ledger", - "writable": true, - "pda": { - "seeds": [ - { - "kind": "const", - "value": [117, 115, 101, 114, 95, 108, 101, 100, 103, 101, 114] - }, - { - "kind": "account", - "path": "owner" - } - ] - } - }, - { - "name": "owner", - "signer": true - }, - { - "name": "payer", - "writable": true, - "signer": true - }, - { - "name": "system_program", - "address": "11111111111111111111111111111111" - } - ], - "args": [] - }, - { - "name": "set_ledger_balance", - "discriminator": [131, 49, 240, 17, 228, 248, 156, 54], - "accounts": [ - { - "name": "ledger", - "writable": true - }, - { - "name": "owner", - "signer": true, - "relations": ["ledger"] - } - ], - "args": [ - { - "name": "amount", - "type": "u64" - }, - { - "name": "is_token_a", - "type": "bool" - } - ] - }, - { - "name": "update_ledger_balance_after_swap", - "discriminator": [59, 206, 173, 232, 94, 57, 174, 202], - "accounts": [ - { - "name": "ledger", - "writable": true - }, - { - "name": "token_account" - }, - { - "name": "owner", - "signer": true, - "relations": ["ledger"] - } - ], - "args": [ - { - "name": "pre_source_token_balance", - "type": "u64" - }, - { - "name": "max_transfer_amount", - "type": "u64" - }, - { - "name": "is_token_a", - "type": "bool" - } - ] - }, - - { - "name": "zap_out", - "discriminator": [155, 108, 185, 112, 104, 210, 161, 64], - "accounts": [ - { - "name": "user_token_in_account", - "writable": true - }, - { - "name": "amm_program" - } - ], - "args": [ - { - "name": "params", - "type": { - "defined": { - "name": "ZapOutParameters" - } - } - } - ] - } - ], - "accounts": [ - { - "name": "UserLedger", - "discriminator": [185, 84, 101, 128, 8, 6, 160, 83] - } - ], - "errors": [ - { - "code": 6000, - "name": "MathOverflow", - "msg": "Math operation overflow" - }, - { - "code": 6001, - "name": "InvalidOffset", - "msg": "Invalid offset" - }, - { - "code": 6002, - "name": "InvalidZapOutParameters", - "msg": "Invalid zapout parameters" - }, - { - "code": 6003, - "name": "TypeCastFailed", - "msg": "Type cast error" - }, - { - "code": 6004, - "name": "AmmIsNotSupported", - "msg": "Amm program is not supported" - }, - { - "code": 6005, - "name": "InvalidPosition", - "msg": "Position is not empty" - }, - { - "code": 6006, - "name": "ExceededSlippage", - "msg": "Exceeded slippage tolerance" - }, - { - "code": 6007, - "name": "InvalidDlmmZapInParameters", - "msg": "Invalid dlmm zap in parameters" - }, - { - "code": 6008, - "name": "UnsupportedFeeMode", - "msg": "Unsupported fee mode" - } - ], - "types": [ - { - "name": "UserLedger", - "serialization": "bytemuck", - "repr": { - "kind": "c" - }, - "type": { - "kind": "struct", - "fields": [ - { - "name": "owner", - "type": "pubkey" - }, - { - "name": "amount_a", - "type": "u64" - }, - { - "name": "amount_b", - "type": "u64" - } - ] - } - }, - { - "name": "ZapOutParameters", - "type": { - "kind": "struct", - "fields": [ - { - "name": "percentage", - "type": "u8" - }, - { - "name": "offset_amount_in", - "type": "u16" - }, - { - "name": "pre_user_token_balance", - "type": "u64" - }, - { - "name": "max_swap_amount", - "type": "u64" - }, - { - "name": "payload_data", - "type": "bytes" - } - ] - } - }, - { - "name": "StrategyType", - "type": { - "kind": "enum", - "variants": [ - { - "name": "SpotOneSide" - }, - { - "name": "CurveOneSide" - }, - { - "name": "BidAskOneSide" - }, - { - "name": "SpotBalanced" - }, - { - "name": "CurveBalanced" - }, - { - "name": "BidAskBalanced" - }, - { - "name": "SpotImBalanced" - }, - { - "name": "CurveImBalanced" - }, - { - "name": "BidAskImBalanced" - } - ] - } - }, - { - "name": "RemainingAccountsInfo", - "type": { - "kind": "struct", - "fields": [ - { - "name": "slices", - "type": { - "vec": { - "defined": { - "name": "RemainingAccountsSlice" - } - } - } - } - ] - } - }, - { - "name": "RemainingAccountsSlice", - "type": { - "kind": "struct", - "fields": [ - { - "name": "accounts_type", - "type": { - "defined": { - "name": "AccountsType" - } - } - }, - { - "name": "length", - "type": "u8" - } - ] - } - }, - { - "name": "AccountsType", - "type": { - "kind": "enum", - "variants": [ - { - "name": "TransferHookX" - }, - { - "name": "TransferHookY" - }, - { - "name": "TransferHookReward" - }, - { - "name": "TransferHookMultiReward", - "fields": ["u8"] - } - ] - } - } - ], - "constants": [ - { - "name": "DAMM_V2_SWAP_DISC", - "type": { - "array": ["u8", 8] - }, - "value": "[248, 198, 158, 145, 225, 117, 135, 200]" - }, - { - "name": "DLMM_SWAP2_DISC", - "type": { - "array": ["u8", 8] - }, - "value": "[65, 75, 63, 76, 235, 91, 91, 136]" - }, - { - "name": "JUP_V6_ROUTE_DISC", - "type": { - "array": ["u8", 8] - }, - "value": "[229, 23, 203, 151, 122, 227, 173, 42]" - }, - { - "name": "JUP_V6_SHARED_ACCOUNT_ROUTE_DISC", - "type": { - "array": ["u8", 8] - }, - "value": "[193, 32, 155, 51, 65, 214, 156, 129]" - }, - { - "name": "MAX_BASIS_POINT", - "type": "u16", - "value": "10000" - }, - { - "name": "USER_LEDGER_PREFIX", - "type": "bytes", - "value": "[117, 115, 101, 114, 95, 108, 101, 100, 103, 101, 114]" - } - ] -} diff --git a/libs/jupiter/Cargo.toml b/libs/jupiter/Cargo.toml deleted file mode 100644 index 0bb65bfb..00000000 --- a/libs/jupiter/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "jupiter" -version = "0.1.0" -description = "Created with Anchor" -edition = "2021" - -[lib] -doctest = false - -[dependencies] -bytemuck = { workspace = true, features = ["derive", "min_const_generics"] } -anchor-lang = { workspace = true } diff --git a/libs/jupiter/src/lib.rs b/libs/jupiter/src/lib.rs deleted file mode 100644 index 5100bfe0..00000000 --- a/libs/jupiter/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -use anchor_lang::prelude::*; - -declare_program!(jupiter); - -pub use jupiter::*; diff --git a/libs/zap/Cargo.toml b/libs/zap/Cargo.toml deleted file mode 100644 index b44901e8..00000000 --- a/libs/zap/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "zap" -version = "0.1.0" -description = "Created with Anchor" -edition = "2021" - -[lib] -doctest = false - -[dependencies] -bytemuck = { workspace = true, features = ["derive", "min_const_generics"] } -anchor-lang = { workspace = true } \ No newline at end of file diff --git a/libs/zap/src/lib.rs b/libs/zap/src/lib.rs deleted file mode 100644 index 6b09fd8e..00000000 --- a/libs/zap/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -use anchor_lang::prelude::*; - -declare_program!(zap); - -pub use zap::*; diff --git a/programs/cp-amm/Cargo.toml b/programs/cp-amm/Cargo.toml index b7d44864..d11dc2f4 100644 --- a/programs/cp-amm/Cargo.toml +++ b/programs/cp-amm/Cargo.toml @@ -32,8 +32,7 @@ const-crypto = "0.3.0" pinocchio = { git = "https://github.com/anza-xyz/pinocchio.git", rev = "17b0e862c01a868ea07ef81a2f8a9b4a504bdfed" } pinocchio-token = { git = "https://github.com/anza-xyz/pinocchio.git", rev = "17b0e862c01a868ea07ef81a2f8a9b4a504bdfed" } pinocchio-token-2022 = { git = "https://github.com/anza-xyz/pinocchio.git", rev = "17b0e862c01a868ea07ef81a2f8a9b4a504bdfed" } -zap = { path = "../../libs/zap" } -jupiter = { path = "../../libs/jupiter" } +protocol-zap = { git = "https://github.com/MeteoraAg/zap-program", rev = "064c58b317b9a85f212c0de72caea286fc72fdb4" } [dev-dependencies] proptest = { workspace = true} diff --git a/programs/cp-amm/src/constants.rs b/programs/cp-amm/src/constants.rs index aebb8791..9a954fc2 100644 --- a/programs/cp-amm/src/constants.rs +++ b/programs/cp-amm/src/constants.rs @@ -1,7 +1,5 @@ use anchor_lang::constant; use anchor_lang::prelude::*; -use anchor_spl::associated_token::ID as ASSOCIATED_TOKEN_PROGRAM_ID; -use anchor_spl::token::ID as TOKEN_PROGRAM_ID; pub const MIN_SQRT_PRICE: u128 = 4295048016; @@ -68,63 +66,6 @@ const OKX_SMART_WALLET: Pubkey = pub const RATE_LIMITER_STACK_WHITELIST_PROGRAMS: [[u8; 32]; 1] = [OKX_SMART_WALLET.to_bytes()]; -pub mod zap { - use super::*; - use ::zap::zap; - use const_crypto::ed25519; - - pub const JUP_V6: Pubkey = pubkey!("JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"); - - pub const JUP_V6_SHARED_ACCOUNT_ROUTE_AMOUNT_IN_REVERSE_OFFSET: usize = 1 + 2 + 8 + 8; // Due to jupiter parameters have dynamic length type (vec), we have to do parameters_data.length - JUP_V6_SHARED_ACCOUNT_ROUTE_AMOUNT_IN_REVERSE_OFFSET - pub const JUP_V6_SHARED_ACCOUNT_ROUTE_SOURCE_ACCOUNT_INDEX: usize = 3; - pub const JUP_V6_SHARED_ACCOUNT_ROUTE_DESTINATION_ACCOUNT_INDEX: usize = 6; - - pub const JUP_V6_ROUTE_AMOUNT_IN_REVERSE_OFFSET: usize = 1 + 2 + 8 + 8; - pub const JUP_V6_ROUTE_SOURCE_ACCOUNT_INDEX: usize = 2; - pub const JUP_V6_ROUTE_DESTINATION_ACCOUNT_INDEX: usize = 4; - - pub const DAMM_V2_SWAP_AMOUNT_IN_OFFSET: u16 = 8; - pub const DAMM_V2_SWAP_SOURCE_ACCOUNT_INDEX: usize = 2; - pub const DAMM_V2_SWAP_DESTINATION_ACCOUNT_INDEX: usize = 3; - - pub const USDC_ADDRESS: Pubkey = - Pubkey::from_str_const("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"); - - pub const SOL_ADDRESS: Pubkey = - Pubkey::from_str_const("So11111111111111111111111111111111111111112"); - - pub const MINTS_DISALLOWED_TO_ZAP_OUT: [Pubkey; 2] = [USDC_ADDRESS, SOL_ADDRESS]; - - pub const TREASURY_USDC_ADDRESS: Pubkey = Pubkey::new_from_array( - ed25519::derive_program_address( - &[ - &treasury::ID.to_bytes(), - &TOKEN_PROGRAM_ID.to_bytes(), - &USDC_ADDRESS.to_bytes(), - ], - &ASSOCIATED_TOKEN_PROGRAM_ID.to_bytes(), - ) - .0, - ); - - pub const TREASURY_SOL_ADDRESS: Pubkey = Pubkey::new_from_array( - ed25519::derive_program_address( - &[ - &treasury::ID.to_bytes(), - &TOKEN_PROGRAM_ID.to_bytes(), - &SOL_ADDRESS.to_bytes(), - ], - &ASSOCIATED_TOKEN_PROGRAM_ID.to_bytes(), - ) - .0, - ); - - pub const DAMM_V2_SWAP_DISC_REF: &[u8] = &zap::constants::DAMM_V2_SWAP_DISC; - pub const JUP_V6_ROUTE_DISC_REF: &[u8] = &zap::constants::JUP_V6_ROUTE_DISC; - pub const JUP_V6_SHARED_ACCOUNT_ROUTE_DISC_REF: &[u8] = - &zap::constants::JUP_V6_SHARED_ACCOUNT_ROUTE_DISC; -} - pub mod activation { #[cfg(not(feature = "local"))] pub const SLOT_BUFFER: u64 = 9000; // 1 slot = 400 mls => 1 hour diff --git a/programs/cp-amm/src/error.rs b/programs/cp-amm/src/error.rs index 2b66c111..0afb83cc 100644 --- a/programs/cp-amm/src/error.rs +++ b/programs/cp-amm/src/error.rs @@ -1,5 +1,6 @@ //! Error module includes error messages and codes of the program use anchor_lang::prelude::*; +use protocol_zap::error::ProtozolZapError; /// Error messages and codes of the program #[error_code] @@ -209,3 +210,20 @@ pub enum PoolError { #[msg("Invalid compounding fee bps")] InvalidCompoundingFeeBps, } + +impl From for PoolError { + fn from(e: ProtozolZapError) -> Self { + match e { + ProtozolZapError::MathOverflow => PoolError::MathOverflow, + ProtozolZapError::InvalidZapOutParameters => PoolError::InvalidZapOutParameters, + ProtozolZapError::TypeCastFailed => PoolError::TypeCastFailed, + ProtozolZapError::MissingZapOutInstruction => PoolError::MissingZapOutInstruction, + ProtozolZapError::InvalidWithdrawProtocolFeeZapAccounts => { + PoolError::InvalidWithdrawProtocolFeeZapAccounts + } + ProtozolZapError::MintRestrictedFromZap => PoolError::MintRestrictedFromZap, + ProtozolZapError::CpiDisabled => PoolError::CpiDisabled, + ProtozolZapError::InvalidZapAccounts => PoolError::InvalidZapAccounts, + } + } +} diff --git a/programs/cp-amm/src/instructions/operator/ix_zap_protocol_fee.rs b/programs/cp-amm/src/instructions/operator/ix_zap_protocol_fee.rs new file mode 100644 index 00000000..60be516c --- /dev/null +++ b/programs/cp-amm/src/instructions/operator/ix_zap_protocol_fee.rs @@ -0,0 +1,156 @@ +use crate::token::{get_token_program_from_flag, validate_ata_token}; +use crate::PoolError; +use crate::{ + const_pda, + constants::treasury as TREASURY, + state::{Operator, Pool}, + token::transfer_from_pool, +}; +use anchor_lang::prelude::*; +use anchor_lang::solana_program::sysvar::instructions::ID as SYSVAR_IX_ID; + +use anchor_spl::associated_token::get_associated_token_address_with_program_id; +use anchor_spl::token_interface::{Mint, TokenAccount, TokenInterface}; +use protocol_zap::constants::MINTS_DISALLOWED_TO_ZAP_OUT; +use protocol_zap::utils::validate_zap_out_to_treasury; + +/// Accounts for zap protocol fees +#[derive(Accounts)] +pub struct ZapProtocolFee<'info> { + /// CHECK: pool authority + #[account(address = const_pda::pool_authority::ID)] + pub pool_authority: UncheckedAccount<'info>, + + #[account(mut)] + pub pool: AccountLoader<'info, Pool>, + + #[account(mut)] + pub token_vault: Box>, + + pub token_mint: Box>, + + /// CHECK: Receiver token account to receive the zap out fund. + #[account(mut)] + pub receiver_token: UncheckedAccount<'info>, + + /// zap claim fee operator + pub operator: AccountLoader<'info, Operator>, + + /// Operator + pub signer: Signer<'info>, + + /// Token program + pub token_program: Interface<'info, TokenInterface>, + + /// CHECK: Sysvar Instructions account + #[account( + address = SYSVAR_IX_ID, + )] + pub sysvar_instructions: AccountInfo<'info>, +} + +fn validate_accounts_and_return_withdraw_direction<'info>( + pool: &Pool, + token_vault: &InterfaceAccount<'info, TokenAccount>, + token_mint: &InterfaceAccount<'info, Mint>, + token_program: &Interface<'info, TokenInterface>, +) -> Result { + require!( + token_mint.key() == pool.token_a_mint || token_mint.key() == pool.token_b_mint, + PoolError::InvalidWithdrawProtocolFeeZapAccounts + ); + + let is_withdrawing_token_a = token_mint.key() == pool.token_a_mint; + + if is_withdrawing_token_a { + require!( + token_vault.key() == pool.token_a_vault, + PoolError::InvalidWithdrawProtocolFeeZapAccounts + ); + } else { + require!( + token_vault.key() == pool.token_b_vault, + PoolError::InvalidWithdrawProtocolFeeZapAccounts + ); + } + + let token_mint_ai = token_mint.to_account_info(); + require!( + *token_mint_ai.owner == token_program.key(), + PoolError::InvalidWithdrawProtocolFeeZapAccounts + ); + + Ok(is_withdrawing_token_a) +} + +// Rules: +// 1. If the token mint is SOL or USDC, then must withdraw to treasury using `claim_protocol_fee` endpoint. No zap out allowed. +// 2. If the token mint is not SOL or USDC, operator require to zap out to SOL or USDC or either one of the token of the pool +pub fn handle_zap_protocol_fee(ctx: Context, max_amount: u64) -> Result<()> { + let mut pool = ctx.accounts.pool.load_mut()?; + let is_withdrawing_a = validate_accounts_and_return_withdraw_direction( + &pool, + &ctx.accounts.token_vault, + &ctx.accounts.token_mint, + &ctx.accounts.token_program, + )?; + + require!( + !MINTS_DISALLOWED_TO_ZAP_OUT.contains(&ctx.accounts.token_mint.key().to_bytes()), + PoolError::MintRestrictedFromZap + ); + + let (amount, treasury_paired_destination_token_address) = if is_withdrawing_a { + let (amount_a, _) = pool.claim_protocol_fee(max_amount, 0)?; + + let treasury_token_b_address = get_associated_token_address_with_program_id( + &TREASURY::ID, + &pool.token_b_mint, + &get_token_program_from_flag(pool.token_b_flag)?, + ); + (amount_a, treasury_token_b_address) + } else { + let (_, amount_b) = pool.claim_protocol_fee(0, max_amount)?; + let treasury_token_a_address = get_associated_token_address_with_program_id( + &TREASURY::ID, + &pool.token_a_mint, + &get_token_program_from_flag(pool.token_a_flag)?, + ); + (amount_b, treasury_token_a_address) + }; + + require!(amount > 0, PoolError::AmountIsZero); + + drop(pool); + + let receiver_token_ai = ctx.accounts.receiver_token.to_account_info(); + + validate_ata_token( + &receiver_token_ai, + &ctx.accounts.signer.key(), + &ctx.accounts.token_mint.key(), + &ctx.accounts.token_program.key(), + )?; + + validate_zap_out_to_treasury( + amount, + &crate::ID.to_bytes(), + &ctx.accounts.receiver_token.key().to_bytes(), + &ctx.accounts.receiver_token.try_borrow_data()?, + &ctx.accounts.sysvar_instructions.try_borrow_data()?, + &TREASURY::ID.to_bytes(), + &treasury_paired_destination_token_address.to_bytes(), + ) + .map_err(|e| -> anchor_lang::error::Error { PoolError::from(e).into() })?; + + transfer_from_pool( + ctx.accounts.pool_authority.to_account_info(), + &ctx.accounts.token_mint, + &ctx.accounts.token_vault, + &receiver_token_ai, + &ctx.accounts.token_program, + amount, + )?; + + Ok(()) +} diff --git a/programs/cp-amm/src/instructions/operator/mod.rs b/programs/cp-amm/src/instructions/operator/mod.rs index e425861a..6350d476 100644 --- a/programs/cp-amm/src/instructions/operator/mod.rs +++ b/programs/cp-amm/src/instructions/operator/mod.rs @@ -20,11 +20,11 @@ pub mod ix_close_token_badge; pub use ix_close_token_badge::*; pub mod ix_update_pool_fees; pub use ix_update_pool_fees::*; -pub mod zap_protocol_fee; -pub use zap_protocol_fee::*; pub mod ix_fix_pool_fee_params; pub use ix_fix_pool_fee_params::*; pub mod ix_fix_config_fee_params; pub use ix_fix_config_fee_params::*; pub mod ix_fix_pool_layout_version; pub use ix_fix_pool_layout_version::*; +pub mod ix_zap_protocol_fee; +pub use ix_zap_protocol_fee::*; diff --git a/programs/cp-amm/src/instructions/operator/zap_protocol_fee/damm_v2_zap.rs b/programs/cp-amm/src/instructions/operator/zap_protocol_fee/damm_v2_zap.rs deleted file mode 100644 index bab42366..00000000 --- a/programs/cp-amm/src/instructions/operator/zap_protocol_fee/damm_v2_zap.rs +++ /dev/null @@ -1,28 +0,0 @@ -use crate::{ - constants::zap::{ - DAMM_V2_SWAP_AMOUNT_IN_OFFSET, DAMM_V2_SWAP_DESTINATION_ACCOUNT_INDEX, - DAMM_V2_SWAP_SOURCE_ACCOUNT_INDEX, - }, - instructions::zap_protocol_fee::{RawZapOutAmmInfo, ZapInfoProcessor}, -}; -use anchor_lang::prelude::*; -use zap::types::ZapOutParameters; - -pub struct ZapDammV2InfoProcessor; - -impl ZapInfoProcessor for ZapDammV2InfoProcessor { - fn validate_payload(&self, _payload: &[u8]) -> Result<()> { - Ok(()) - } - - fn extract_raw_zap_out_amm_info( - &self, - _zap_params: &ZapOutParameters, - ) -> Result { - Ok(RawZapOutAmmInfo { - source_index: DAMM_V2_SWAP_SOURCE_ACCOUNT_INDEX, - destination_index: DAMM_V2_SWAP_DESTINATION_ACCOUNT_INDEX, - amount_in_offset: DAMM_V2_SWAP_AMOUNT_IN_OFFSET, - }) - } -} diff --git a/programs/cp-amm/src/instructions/operator/zap_protocol_fee/jup_v6_zap.rs b/programs/cp-amm/src/instructions/operator/zap_protocol_fee/jup_v6_zap.rs deleted file mode 100644 index 1aaf1328..00000000 --- a/programs/cp-amm/src/instructions/operator/zap_protocol_fee/jup_v6_zap.rs +++ /dev/null @@ -1,95 +0,0 @@ -use crate::{ - constants::zap::{ - JUP_V6_ROUTE_AMOUNT_IN_REVERSE_OFFSET, JUP_V6_ROUTE_DESTINATION_ACCOUNT_INDEX, - JUP_V6_ROUTE_SOURCE_ACCOUNT_INDEX, JUP_V6_SHARED_ACCOUNT_ROUTE_AMOUNT_IN_REVERSE_OFFSET, - JUP_V6_SHARED_ACCOUNT_ROUTE_DESTINATION_ACCOUNT_INDEX, - JUP_V6_SHARED_ACCOUNT_ROUTE_SOURCE_ACCOUNT_INDEX, - }, - instructions::zap_protocol_fee::{RawZapOutAmmInfo, ZapInfoProcessor}, - math::safe_math::{SafeCast, SafeMath}, - PoolError, -}; -use anchor_lang::prelude::*; -use jupiter::types::RoutePlanStep; -use jupiter::types::Swap; -use zap::types::ZapOutParameters; - -pub struct ZapJupV6RouteInfoProcessor; - -fn ensure_whitelisted_swap_leg(route_plan_steps: &[RoutePlanStep]) -> Result<()> { - for step in route_plan_steps { - match step.swap { - Swap::Meteora - | Swap::MeteoraDammV2 - | Swap::MeteoraDammV2WithRemainingAccounts - | Swap::MeteoraDlmm - | Swap::MeteoraDlmmSwapV2 { .. } - | Swap::Mercurial - | Swap::Whirlpool { .. } - | Swap::WhirlpoolSwapV2 { .. } - | Swap::Raydium - | Swap::RaydiumV2 - | Swap::RaydiumCP - | Swap::RaydiumClmm - | Swap::RaydiumClmmV2 => { - // whitelisted swap leg - } - _ => return Err(PoolError::InvalidZapOutParameters.into()), - } - } - - Ok(()) -} - -impl ZapInfoProcessor for ZapJupV6RouteInfoProcessor { - fn validate_payload(&self, payload: &[u8]) -> Result<()> { - let route_params = jupiter::client::args::Route::try_from_slice(payload)?; - ensure_whitelisted_swap_leg(&route_params.route_plan)?; - - Ok(()) - } - - fn extract_raw_zap_out_amm_info( - &self, - zap_params: &ZapOutParameters, - ) -> Result { - let amount_in_offset = zap_params - .payload_data - .len() - .safe_sub(JUP_V6_ROUTE_AMOUNT_IN_REVERSE_OFFSET)? - .safe_cast()?; - - Ok(RawZapOutAmmInfo { - source_index: JUP_V6_ROUTE_SOURCE_ACCOUNT_INDEX, - destination_index: JUP_V6_ROUTE_DESTINATION_ACCOUNT_INDEX, - amount_in_offset, - }) - } -} - -pub struct ZapJupV6SharedRouteInfoProcessor; - -impl ZapInfoProcessor for ZapJupV6SharedRouteInfoProcessor { - fn validate_payload(&self, payload: &[u8]) -> Result<()> { - let route_params = jupiter::client::args::SharedAccountsRoute::try_from_slice(payload)?; - ensure_whitelisted_swap_leg(&route_params.route_plan)?; - Ok(()) - } - - fn extract_raw_zap_out_amm_info( - &self, - zap_params: &ZapOutParameters, - ) -> Result { - let amount_in_offset = zap_params - .payload_data - .len() - .safe_sub(JUP_V6_SHARED_ACCOUNT_ROUTE_AMOUNT_IN_REVERSE_OFFSET)? - .safe_cast()?; - - Ok(RawZapOutAmmInfo { - source_index: JUP_V6_SHARED_ACCOUNT_ROUTE_SOURCE_ACCOUNT_INDEX, - destination_index: JUP_V6_SHARED_ACCOUNT_ROUTE_DESTINATION_ACCOUNT_INDEX, - amount_in_offset, - }) - } -} diff --git a/programs/cp-amm/src/instructions/operator/zap_protocol_fee/mod.rs b/programs/cp-amm/src/instructions/operator/zap_protocol_fee/mod.rs deleted file mode 100644 index 4d4da849..00000000 --- a/programs/cp-amm/src/instructions/operator/zap_protocol_fee/mod.rs +++ /dev/null @@ -1,45 +0,0 @@ -use anchor_lang::prelude::*; -use zap::types::ZapOutParameters; - -use crate::{ - constants::zap::{ - DAMM_V2_SWAP_DISC_REF, JUP_V6, JUP_V6_ROUTE_DISC_REF, JUP_V6_SHARED_ACCOUNT_ROUTE_DISC_REF, - }, - zap_protocol_fee::{ - damm_v2_zap::ZapDammV2InfoProcessor, - jup_v6_zap::{ZapJupV6RouteInfoProcessor, ZapJupV6SharedRouteInfoProcessor}, - }, - PoolError, -}; -mod damm_v2_zap; -mod process_zap_protocol_fee; -pub use process_zap_protocol_fee::*; -mod jup_v6_zap; - -pub struct RawZapOutAmmInfo { - source_index: usize, - destination_index: usize, - amount_in_offset: u16, -} - -pub trait ZapInfoProcessor { - fn validate_payload(&self, payload: &[u8]) -> Result<()>; - fn extract_raw_zap_out_amm_info( - &self, - zap_params: &ZapOutParameters, - ) -> Result; -} - -pub fn get_zap_amm_processor( - amm_disc: &[u8], - amm_program_address: Pubkey, -) -> Result> { - match (amm_disc, amm_program_address) { - (DAMM_V2_SWAP_DISC_REF, crate::ID_CONST) => Ok(Box::new(ZapDammV2InfoProcessor)), - (JUP_V6_ROUTE_DISC_REF, JUP_V6) => Ok(Box::new(ZapJupV6RouteInfoProcessor)), - (JUP_V6_SHARED_ACCOUNT_ROUTE_DISC_REF, JUP_V6) => { - Ok(Box::new(ZapJupV6SharedRouteInfoProcessor)) - } - _ => Err(PoolError::InvalidZapOutParameters.into()), - } -} diff --git a/programs/cp-amm/src/instructions/operator/zap_protocol_fee/process_zap_protocol_fee.rs b/programs/cp-amm/src/instructions/operator/zap_protocol_fee/process_zap_protocol_fee.rs deleted file mode 100644 index 6b5dba6d..00000000 --- a/programs/cp-amm/src/instructions/operator/zap_protocol_fee/process_zap_protocol_fee.rs +++ /dev/null @@ -1,355 +0,0 @@ -use crate::constants::zap::{ - MINTS_DISALLOWED_TO_ZAP_OUT, TREASURY_SOL_ADDRESS, TREASURY_USDC_ADDRESS, -}; -use crate::safe_math::SafeMath; -use crate::token::{get_token_program_from_flag, validate_ata_token}; -use crate::{ - const_pda, - constants::treasury as TREASURY, - state::{Operator, Pool}, - token::transfer_from_pool, -}; -use crate::{get_zap_amm_processor, PoolError, RawZapOutAmmInfo}; -use anchor_lang::prelude::*; -use anchor_lang::solana_program::sysvar::instructions::ID as SYSVAR_IX_ID; -use anchor_lang::solana_program::sysvar::instructions::{ - load_current_index_checked, load_instruction_at_checked, -}; -use anchor_spl::associated_token::get_associated_token_address_with_program_id; -use anchor_spl::token::accessor; -use anchor_spl::token_interface::{Mint, TokenAccount, TokenInterface}; -use zap::types::ZapOutParameters; - -/// Accounts for zap protocol fees -#[derive(Accounts)] -pub struct ZapProtocolFee<'info> { - /// CHECK: pool authority - #[account(address = const_pda::pool_authority::ID)] - pub pool_authority: UncheckedAccount<'info>, - - #[account(mut)] - pub pool: AccountLoader<'info, Pool>, - - #[account(mut)] - pub token_vault: Box>, - - pub token_mint: Box>, - - /// CHECK: Receiver token account to receive the zap out fund. - #[account(mut)] - pub receiver_token: UncheckedAccount<'info>, - - /// zap claim fee operator - pub operator: AccountLoader<'info, Operator>, - - /// Operator - pub signer: Signer<'info>, - - /// Token program - pub token_program: Interface<'info, TokenInterface>, - - /// CHECK: Sysvar Instructions account - #[account( - address = SYSVAR_IX_ID, - )] - pub sysvar_instructions: AccountInfo<'info>, -} - -fn validate_accounts_and_return_withdraw_direction<'info>( - pool: &Pool, - token_vault: &InterfaceAccount<'info, TokenAccount>, - token_mint: &InterfaceAccount<'info, Mint>, - token_program: &Interface<'info, TokenInterface>, -) -> Result { - require!( - token_mint.key() == pool.token_a_mint || token_mint.key() == pool.token_b_mint, - PoolError::InvalidWithdrawProtocolFeeZapAccounts - ); - - let is_withdrawing_token_a = token_mint.key() == pool.token_a_mint; - - if is_withdrawing_token_a { - require!( - token_vault.key() == pool.token_a_vault, - PoolError::InvalidWithdrawProtocolFeeZapAccounts - ); - } else { - require!( - token_vault.key() == pool.token_b_vault, - PoolError::InvalidWithdrawProtocolFeeZapAccounts - ); - } - - let token_mint_ai = token_mint.to_account_info(); - require!( - *token_mint_ai.owner == token_program.key(), - PoolError::InvalidWithdrawProtocolFeeZapAccounts - ); - - Ok(is_withdrawing_token_a) -} - -// Rules: -// 1. If the token mint is SOL or USDC, then must withdraw to treasury using `claim_protocol_fee` endpoint. No zap out allowed. -// 2. If the token mint is not SOL or USDC, operator require to zap out to SOL or USDC or either one of the token of the pool -pub fn handle_zap_protocol_fee(ctx: Context, max_amount: u64) -> Result<()> { - let mut pool = ctx.accounts.pool.load_mut()?; - let is_withdrawing_a = validate_accounts_and_return_withdraw_direction( - &pool, - &ctx.accounts.token_vault, - &ctx.accounts.token_mint, - &ctx.accounts.token_program, - )?; - - require!( - !MINTS_DISALLOWED_TO_ZAP_OUT.contains(&ctx.accounts.token_mint.key()), - PoolError::MintRestrictedFromZap - ); - - let (amount, treasury_paired_destination_token_address) = if is_withdrawing_a { - let (amount_a, _) = pool.claim_protocol_fee(max_amount, 0)?; - - let treasury_token_b_address = get_associated_token_address_with_program_id( - &TREASURY::ID, - &pool.token_b_mint, - &get_token_program_from_flag(pool.token_b_flag)?, - ); - (amount_a, treasury_token_b_address) - } else { - let (_, amount_b) = pool.claim_protocol_fee(0, max_amount)?; - let treasury_token_a_address = get_associated_token_address_with_program_id( - &TREASURY::ID, - &pool.token_a_mint, - &get_token_program_from_flag(pool.token_a_flag)?, - ); - (amount_b, treasury_token_a_address) - }; - - require!(amount > 0, PoolError::AmountIsZero); - - drop(pool); - - let receiver_token_ai = ctx.accounts.receiver_token.to_account_info(); - - validate_ata_token( - &receiver_token_ai, - &ctx.accounts.signer.key(), - &ctx.accounts.token_mint.key(), - &ctx.accounts.token_program.key(), - )?; - - validate_zap_out_to_treasury( - amount, - &receiver_token_ai, - treasury_paired_destination_token_address, - &ctx.accounts.sysvar_instructions, - )?; - - transfer_from_pool( - ctx.accounts.pool_authority.to_account_info(), - &ctx.accounts.token_mint, - &ctx.accounts.token_vault, - &receiver_token_ai, - &ctx.accounts.token_program, - amount, - )?; - - Ok(()) -} - -fn validate_zap_out_to_treasury<'info>( - claimed_amount: u64, - claimer_token_account: &AccountInfo<'info>, - treasury_paired_destination_token_address: Pubkey, - sysvar_instructions_account: &AccountInfo<'info>, -) -> Result<()> { - let current_index = load_current_index_checked(sysvar_instructions_account)?; - - let current_instruction = - load_instruction_at_checked(current_index.into(), sysvar_instructions_account)?; - - // Ensure the instruction is direct instruction call - require!( - current_instruction.program_id == crate::ID, - PoolError::CpiDisabled - ); - - search_and_validate_zap_out_instruction( - current_index, - claimed_amount, - sysvar_instructions_account, - claimer_token_account, - treasury_paired_destination_token_address, - ) -} - -// Search for zap out instruction in the next instruction after the current one -fn search_and_validate_zap_out_instruction<'info>( - current_index: u16, - max_claim_amount: u64, - sysvar_instructions_account: &AccountInfo<'info>, - claimer_token_account: &AccountInfo<'info>, - treasury_paired_destination_token_address: Pubkey, -) -> Result<()> { - // Zap out instruction must be next to current instruction - let next_index = current_index.safe_add(1)?; - let ix = load_instruction_at_checked(next_index.into(), sysvar_instructions_account)?; - - require!( - ix.program_id == zap::ID, - PoolError::MissingZapOutInstruction - ); - - let disc = ix - .data - .get(..8) - .ok_or_else(|| PoolError::InvalidZapOutParameters)?; - - require!( - disc == zap::client::args::ZapOut::DISCRIMINATOR, - PoolError::MissingZapOutInstruction - ); - - let zap_params = ZapOutParameters::try_from_slice(&ix.data[8..])?; - - let ZapOutAmmInfo { - zap_user_token_in_address, - amm_source_token_address: source_token_address, - amm_destination_token_address: destination_token_address, - amount_in_offset, - } = extract_amm_accounts_and_info(&zap_params, &ix.accounts)?; - - // Zap out from operator fee receiving account - validate_zap_parameters( - &zap_params, - max_claim_amount, - amount_in_offset, - claimer_token_account, - )?; - - // There's no validation to make sure that `user_token_in_account` is the same as `amm_source_token_address` - // Operator could steal the fund by providing a fake token account with 0 to bypass the zap swap invoke - // https://github.com/MeteoraAg/zap-program/blob/117e7d5586aa27cf97e6fde6266e25ee4e496f18/programs/zap/src/instructions/ix_zap_out.rs#L91 - require!( - zap_user_token_in_address == claimer_token_account.key(), - PoolError::InvalidZapAccounts - ); - - // Zap out from operator fee receiving account - require!( - source_token_address == claimer_token_account.key(), - PoolError::InvalidZapAccounts - ); - - // Zap to paired mint in the pool, or SOL, or USDC treasury - require!( - destination_token_address == treasury_paired_destination_token_address - || destination_token_address == TREASURY_USDC_ADDRESS - || destination_token_address == TREASURY_SOL_ADDRESS, - PoolError::InvalidZapAccounts - ); - - Ok(()) -} - -fn validate_zap_parameters<'info>( - zap_params: &ZapOutParameters, - max_claim_amount: u64, - amount_in_offset: u16, - claimer_token_account: &AccountInfo<'info>, -) -> Result<()> { - require!( - zap_params.percentage == 100, - PoolError::InvalidZapOutParameters - ); - - require!( - zap_params.offset_amount_in == amount_in_offset, - PoolError::InvalidZapOutParameters - ); - - // Ensure no stealing from operator by setting a higher pre_token_balance than actual balance to steal fund - // Eg: Operator set 100 pre balance, but actual balance is 0 - // Actual claimed amount is 300 - // Zap will attempt to swap post - pre = 300 - 100 = 200 - // Leftover 100 will be stolen by operator - require!( - zap_params.pre_user_token_balance == accessor::amount(claimer_token_account)?, - PoolError::InvalidZapOutParameters - ); - - require!( - zap_params.max_swap_amount == max_claim_amount, - PoolError::InvalidZapOutParameters - ); - - Ok(()) -} - -struct ZapOutAmmInfo { - // Account used to compare delta changes with pre_balance to decide swap amount - zap_user_token_in_address: Pubkey, - amm_source_token_address: Pubkey, - amm_destination_token_address: Pubkey, - amount_in_offset: u16, -} - -fn extract_amm_accounts_and_info( - zap_params: &ZapOutParameters, - zap_account: &[AccountMeta], -) -> Result { - // Accounts in ZapOutCtx - const ZAP_OUT_ACCOUNTS_LEN: usize = 2; - - let zap_user_token_in_address = zap_account - .get(0) - .map(|acc| acc.pubkey) - .ok_or_else(|| PoolError::InvalidZapAccounts)?; - - let zap_amm_program_address = zap_account - .get(1) - .map(|acc| acc.pubkey) - .ok_or_else(|| PoolError::InvalidZapAccounts)?; - - let amm_disc = zap_params - .payload_data - .get(..8) - .ok_or_else(|| PoolError::InvalidZapOutParameters)?; - - let zap_info_processor = get_zap_amm_processor(amm_disc, zap_amm_program_address)?; - - let amm_payload = zap_params - .payload_data - .get(8..) - .ok_or_else(|| PoolError::InvalidZapOutParameters)?; - - zap_info_processor.validate_payload(&amm_payload)?; - - let RawZapOutAmmInfo { - source_index, - destination_index, - amount_in_offset, - } = zap_info_processor.extract_raw_zap_out_amm_info(zap_params)?; - - // Start from remaining accounts of zap program - let amm_accounts = zap_account - .get(ZAP_OUT_ACCOUNTS_LEN..) - .ok_or_else(|| PoolError::InvalidZapAccounts)?; - - let source_token_address = amm_accounts - .get(source_index) - .map(|acc| acc.pubkey) - .ok_or_else(|| PoolError::InvalidZapAccounts)?; - - let destination_token_address = amm_accounts - .get(destination_index) - .map(|acc| acc.pubkey) - .ok_or_else(|| PoolError::InvalidZapAccounts)?; - - Ok(ZapOutAmmInfo { - zap_user_token_in_address, - amm_source_token_address: source_token_address, - amm_destination_token_address: destination_token_address, - amount_in_offset, - }) -}