// file: kb-lib/src/materializer/fees/core.rs // version: 3 //! Stable fee projections derived from exact committed Token-2022 observations. const ACCEPTED_FAMILIES: &[crate::MdEventFamily] = &[crate::MdEventFamily::Fee]; const SPL_TOKEN2022_SURFACE: &str = "spl_token2022"; const TOKEN2022_FEE_ENTRIES: &[&str] = &[ "initialize_transfer_fee_config", "set_transfer_fee", "withdraw_withheld_tokens_from_mint", "withdraw_withheld_tokens_from_accounts", "harvest_withheld_tokens_to_mint", "transfer_checked_with_fee", "initialize_confidential_transfer_fee_config", "withdraw_confidential_withheld_tokens_from_mint", "withdraw_confidential_withheld_tokens_from_accounts", "harvest_confidential_withheld_tokens_to_mint", "enable_confidential_harvest_to_mint", "disable_confidential_harvest_to_mint", "transfer_confidential_tokens_with_fee", ]; /// Fee materializer for committed Token-2022 fee instructions. #[derive(Clone, Debug, Default)] pub struct MtFeesMaterializer; impl crate::MtMaterializer for crate::MtFeesMaterializer { fn materializer_name(&self) -> &'static str { return "kb_materializer_fees"; } fn materializer_version(&self) -> &'static str { return env!("CARGO_PKG_VERSION"); } fn accepts_event(&self, event: &crate::MdDecodedProtocolEvent) -> bool { return accepts_event(event); } fn materialize_event( &self, _event: &crate::MdDecodedProtocolEvent, ) -> kb_core::Result> { return std::result::Result::Ok(std::vec::Vec::new()); } } impl crate::MtApiEventMaterializer for crate::MtFeesMaterializer { fn identity(&self) -> crate::MtApiMaterializerIdentity { return crate::MtApiMaterializerIdentity { name: "fees".to_string(), version: env!("CARGO_PKG_VERSION").to_string(), }; } fn accepted_families(&self) -> &'static [crate::MdEventFamily] { return ACCEPTED_FAMILIES; } fn accepts_observation(&self, observation: &crate::DcApiDecodedObservation) -> bool { return accepts_event(&observation.event); } fn transaction_policy( &self, _family: crate::MdEventFamily, ) -> crate::MtApiMaterializationTransactionPolicy { return crate::MtApiMaterializationTransactionPolicy::SuccessfulCommittedOnly; } fn materialize( &self, observation: &crate::DcApiDecodedObservation, ) -> crate::MtApiMaterializerExecutionResult { if !accepts_event(&observation.event) { return crate::MtApiMaterializerExecutionResult::ignored(); } if observation.transaction_failed || !observation.observation_committed { return crate::MtApiMaterializerExecutionResult::refused( "failed_transaction_fee_refused", "failed or uncommitted Token-2022 observations cannot create fee outputs", ); } let operation = observation.event.event_name.0.clone(); let accounts = observation .payload_json .get("accounts") .cloned() .unwrap_or(serde_json::Value::Null); let parameters = observation .payload_json .get("parameters") .cloned() .unwrap_or_else(|| return observation.payload_json.clone()); let output = crate::MtApiMaterializedOutput { output_key: format!("token2022_fee:{operation}:0"), family: crate::MdMaterializedEventFamily::Fee, payload_json: serde_json::json!({ "projectionVersion": 1, "projectionSemantics": "committed_instruction_fee_event", "domain": fee_domain(observation.event.event_name.0.as_str()), "operation": operation, "programId": observation.event.program_id.0.clone(), "signature": observation.event.signature.0.clone(), "slot": observation.event.slot.0, "instructionPath": observation.event.instruction_path.0.clone(), "transactionSucceeded": true, "accounts": accounts, "parameters": parameters, "stateReadRequired": state_read_required( observation.event.event_name.0.as_str(), ), "confidentialValuesDecrypted": false, }), }; return crate::MtApiMaterializerExecutionResult { status: crate::MtApiMaterializerOutcomeStatus::Inserted, outputs: std::vec![output], diagnostics: std::vec::Vec::new(), }; } } fn accepts_event(event: &crate::MdDecodedProtocolEvent) -> bool { return event.event_family == crate::MdEventFamily::Fee && event.surface_code.0 == SPL_TOKEN2022_SURFACE && event.program_id.0 == kb_program_ids::SPL_TOKEN2022_PROGRAM_ID && contains(TOKEN2022_FEE_ENTRIES, event.event_name.0.as_str()); } fn fee_domain(operation: &str) -> &'static str { if operation.contains("confidential") { return "token2022_confidential_transfer_fee"; } return "token2022_transfer_fee"; } fn state_read_required(operation: &str) -> bool { return matches!( operation, "initialize_transfer_fee_config" | "set_transfer_fee" | "withdraw_withheld_tokens_from_mint" | "withdraw_withheld_tokens_from_accounts" | "harvest_withheld_tokens_to_mint" | "initialize_confidential_transfer_fee_config" | "withdraw_confidential_withheld_tokens_from_mint" | "withdraw_confidential_withheld_tokens_from_accounts" | "harvest_confidential_withheld_tokens_to_mint" | "enable_confidential_harvest_to_mint" | "disable_confidential_harvest_to_mint" ); } fn contains(entries: &[&str], entry_code: &str) -> bool { return entries.iter().any(|entry| return *entry == entry_code); } /// Materialize authoritative Token-2022 fee extension snapshots without decrypting confidential values. pub fn materializer_fees_materialize_token2022_state_snapshots( account_key: &str, slot: u64, state: &crate::DcToken2022State, ) -> std::result::Result, String> { if account_key.is_empty() { return std::result::Result::Err( "Token-2022 fee state snapshot requires a non-empty account key".to_string(), ); } let state_kind = match state.kind { crate::DcToken2022StateKind::Mint => "mint", crate::DcToken2022StateKind::Account => "account", crate::DcToken2022StateKind::Multisig => { return std::result::Result::Err( "Token-2022 multisig state cannot contain fee extensions".to_string(), ); }, }; let mut outputs = std::vec::Vec::new(); for entry in &state.extensions { let confidential = match entry.extension_name { "transfer_fee_config" | "transfer_fee_amount" => false, "confidential_transfer_fee_config" | "confidential_transfer_fee_amount" => true, _ => continue, }; let expected_kind = match entry.extension_name { "transfer_fee_config" | "confidential_transfer_fee_config" => "mint", "transfer_fee_amount" | "confidential_transfer_fee_amount" => "account", _ => continue, }; if state_kind != expected_kind { return std::result::Result::Err(format!( "Token-2022 {} extension requires {expected_kind} state, got {state_kind}", entry.extension_name )); } outputs.push(crate::MtApiMaterializedOutput { output_key: format!( "token2022_fee_state:{}:{account_key}:{slot}", entry.extension_name ), family: crate::MdMaterializedEventFamily::Fee, payload_json: serde_json::json!({ "projectionVersion": 1, "projectionSemantics": "authoritative_bounded_fee_state_snapshot", "domain": if confidential { "token2022_confidential_transfer_fee_state" } else { "token2022_transfer_fee_state" }, "idempotenceKey": format!( "token2022_fee_state:{}:{account_key}:{slot}", entry.extension_name ), "accountKey": account_key, "slot": slot, "programId": kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, "stateKind": state_kind, "extensionType": entry.extension_type, "extensionName": entry.extension_name, "valueHex": entry.value_hex, "valueFields": entry.value_fields, "containsConfidentialState": confidential, "confidentialValuesDecrypted": false, "finalAccountStateCaptured": true, "provenance": { "processorName": "fees", "processorVersion": env!("CARGO_PKG_VERSION"), "source": "bounded_token2022_state_parser" } }), }); } return std::result::Result::Ok(outputs); } #[cfg(test)] mod tests { fn observation( surface_code: &str, program_id: &str, entry_code: &str, transaction_failed: bool, ) -> crate::DcApiDecodedObservation { return crate::DcApiDecodedObservation { event_key: format!("{entry_code}:0"), event: crate::MdDecodedProtocolEvent { signature: crate::MdSignature("signature".to_string()), slot: crate::MdSlot(42), instruction_path: crate::MdInstructionPath("0".to_string()), program_id: crate::MdProgramId(program_id.to_string()), protocol_code: crate::MdProtocolCode("spl_token2022".to_string()), surface_code: crate::MdSurfaceCode(surface_code.to_string()), event_code: crate::MdEventCode(format!("{surface_code}.{entry_code}")), event_name: crate::MdEventName(entry_code.to_string()), event_family: crate::MdEventFamily::Fee, source_kind: crate::MdEventSourceKind::Instruction, confidence: crate::MdDecoderConfidence::ManualExact, }, payload_json: serde_json::json!({ "accounts": [{"position": 0, "role": "mint", "accountKey": "mint111"}], "parameters": {"extension": "transfer_fee", "basisPoints": 25}, }), transaction_failed, transaction_error: if transaction_failed { std::option::Option::Some(serde_json::json!({"InstructionError": [0, "Custom"]})) } else { std::option::Option::None }, observation_committed: !transaction_failed, proof: crate::DcApiDecoderProof { kind: crate::DcApiDecoderProofKind::Manual, confidence: crate::MdDecoderConfidence::ManualExact, evidence: std::vec!["fixture".to_string()], }, }; } #[test] fn committed_token2022_fee_instruction_creates_one_stable_output() { let observation = observation( super::SPL_TOKEN2022_SURFACE, kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, "set_transfer_fee", false, ); let result = crate::MtApiEventMaterializer::materialize(&crate::MtFeesMaterializer, &observation); assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs.len(), 1); assert_eq!(result.outputs[0].family, crate::MdMaterializedEventFamily::Fee); assert_eq!(result.outputs[0].output_key, "token2022_fee:set_transfer_fee:0"); assert_eq!(result.outputs[0].payload_json["stateReadRequired"], true); } #[test] fn failed_token2022_fee_instruction_is_refused() { let observation = observation( super::SPL_TOKEN2022_SURFACE, kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, "harvest_withheld_tokens_to_mint", true, ); let result = crate::MtApiEventMaterializer::materialize(&crate::MtFeesMaterializer, &observation); assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Refused); assert!(result.outputs.is_empty()); } #[test] fn classic_token_and_program_surface_mismatches_are_ignored() { let classic = observation( "spl_token", kb_program_ids::SPL_TOKEN_PROGRAM_ID, "set_transfer_fee", false, ); let wrong_program = observation( super::SPL_TOKEN2022_SURFACE, kb_program_ids::SPL_TOKEN_PROGRAM_ID, "set_transfer_fee", false, ); assert!(!crate::MtApiEventMaterializer::accepts_observation( &crate::MtFeesMaterializer, &classic, )); assert!(!crate::MtApiEventMaterializer::accepts_observation( &crate::MtFeesMaterializer, &wrong_program, )); } #[test] fn transfer_checked_with_fee_is_self_contained_but_state_mutations_are_not() { assert!(!super::state_read_required("transfer_checked_with_fee")); assert!(super::state_read_required("withdraw_withheld_tokens_from_accounts")); } #[test] fn committed_confidential_fee_instruction_is_projected_without_decryption() { let observation = observation( super::SPL_TOKEN2022_SURFACE, kb_program_ids::SPL_TOKEN2022_PROGRAM_ID, "initialize_confidential_transfer_fee_config", false, ); let result = crate::MtApiEventMaterializer::materialize(&crate::MtFeesMaterializer, &observation); assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted); assert_eq!(result.outputs.len(), 1); assert_eq!(result.outputs[0].payload_json["domain"], "token2022_confidential_transfer_fee"); assert_eq!(result.outputs[0].payload_json["stateReadRequired"], true); assert_eq!(result.outputs[0].payload_json["confidentialValuesDecrypted"], false); } #[test] fn confidential_transfer_with_fee_is_instructionally_self_contained() { assert!(!super::state_read_required("transfer_confidential_tokens_with_fee",)); assert_eq!( super::fee_domain("transfer_confidential_tokens_with_fee"), "token2022_confidential_transfer_fee" ); } #[test] fn public_fee_state_snapshots_are_owned_once_and_idempotent() { let mint = crate::DcToken2022State { kind: crate::DcToken2022StateKind::Mint, base_fields: serde_json::json!({}), base_hex: "00".to_string(), account_type: std::option::Option::Some(1), extensions: std::vec![crate::DcToken2022TlvEntry { extension_type: 1, extension_name: "transfer_fee_config", value_hex: "01".to_string(), value_fields: serde_json::json!({"withheldAmount":"7"}), }], }; let first = crate::materializer_fees_materialize_token2022_state_snapshots("mint111", 42, &mint); let second = crate::materializer_fees_materialize_token2022_state_snapshots("mint111", 42, &mint); assert!(first.is_ok()); assert_eq!(first, second); let outputs = match first { std::result::Result::Ok(outputs) => outputs, std::result::Result::Err(error) => panic!("unexpected error: {error}"), }; assert_eq!(outputs.len(), 1); assert_eq!(outputs[0].payload_json["stateKind"], "mint"); assert_eq!(outputs[0].payload_json["valueFields"]["withheldAmount"], "7"); assert_eq!(outputs[0].payload_json["confidentialValuesDecrypted"], false); } #[test] fn confidential_fee_amount_preserves_ciphertext_without_decryption_claim() { let account = crate::DcToken2022State { kind: crate::DcToken2022StateKind::Account, base_fields: serde_json::json!({}), base_hex: "00".to_string(), account_type: std::option::Option::Some(2), extensions: std::vec![crate::DcToken2022TlvEntry { extension_type: 17, extension_name: "confidential_transfer_fee_amount", value_hex: "02".to_string(), value_fields: serde_json::json!({"withheldAmount":"ciphertext"}), }], }; let result = crate::materializer_fees_materialize_token2022_state_snapshots( "account111", 43, &account, ); assert!(result.is_ok()); let outputs = match result { std::result::Result::Ok(outputs) => outputs, std::result::Result::Err(error) => panic!("unexpected error: {error}"), }; assert_eq!(outputs[0].payload_json["containsConfidentialState"], true); assert_eq!(outputs[0].payload_json["confidentialValuesDecrypted"], false); assert_eq!(outputs[0].payload_json["valueFields"]["withheldAmount"], "ciphertext"); } #[test] fn fee_state_snapshot_rejects_wrong_state_kind_and_empty_identity() { let wrong = crate::DcToken2022State { kind: crate::DcToken2022StateKind::Account, base_fields: serde_json::json!({}), base_hex: "00".to_string(), account_type: std::option::Option::Some(2), extensions: std::vec![crate::DcToken2022TlvEntry { extension_type: 1, extension_name: "transfer_fee_config", value_hex: "01".to_string(), value_fields: serde_json::json!({}), }], }; assert!( crate::materializer_fees_materialize_token2022_state_snapshots( "account111", 44, &wrong, ) .is_err() ); assert!( crate::materializer_fees_materialize_token2022_state_snapshots("", 44, &wrong,) .is_err() ); } }