What changed, and why it matters
This commit only adds and updates unit tests for the Tron app in the Keystone 3 firmware. It does not change any production code logic. The tests cover signing, parsing, address generation, and edge cases for transaction formatting. There is no indication of a security fix or vulnerability being addressed.
No security action required. Treat as routine test coverage improvement.
Security signals we found
No production code changes
Only test additions and formatting
No security-relevant keywords in commit title or message
No references to CVEs, advisories, or security issues
Evidence from the diff
The diff is limited to three Rust files under rust/apps/tron. It adds a large number of unit tests in lib.rs and wrapped_tron.rs, plus a minor formatting change in structs.rs. No production functions were modified. The tests exercise existing APIs such as sign_tx_request, check_tx_request, parse_personal_message, decode_to_wrapped, WrappedTron::from_payload, and format_amount. No patch, behavior change, or vulnerability remediation is present in the diff.
Changed components
rust/apps/tron/src/lib.rsrust/apps/tron/src/structs.rsrust/apps/tron/src/transaction/wrapped_tron.rsInspect captured patch +398 / −6
diff --git a/rust/apps/tron/src/lib.rs b/rust/apps/tron/src/lib.rs
index 9cdd2b5..77adf2e 100644
--- a/rust/apps/tron/src/lib.rs
+++ b/rust/apps/tron/src/lib.rs
@@ -205,4 +205,257 @@ mod test {
std::println!("Parsed Value: {}", parsed.overview.value);
}
+
+ #[test]
+ fn test_sign_tx_request() {
+ let path = "m/44'/195'/0'/0/0".to_string();
+ let mock_pb_hex = "0a0207902208e1b9de559665c6714080c49789bb2c5aae01081f12a9010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e747261637412740a1541ad8593979840130d222238380b080808080808081215410d292c98a5eca06c2085fff993996423cf66c93b2244a9059cbb0000000000000000000000009bbce520d984c3b95ad10cb4e32a9294e6338da300000000000000000000000000000000000000000000000000000000000f424070c0b6e087bb2c90018094ebdc03";
+ let sign_data = hex::decode(mock_pb_hex).unwrap();
+ let seed = hex::decode("5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4").unwrap();
+
+ let result = sign_tx_request(&sign_data, &path, &seed);
+ assert!(result.is_ok());
+ let sig = result.unwrap();
+ assert!(!sig.is_empty());
+ assert_eq!(sig.len(), 130); // 65 bytes in hex = 130 chars
+ }
+
+ #[test]
+ fn test_check_tx_request_valid() {
+ // Use valid protobuf data from parse_tx_request test
+ let path = "m/44'/195'/0'/0/0".to_string();
+ let xpub = "xpub6D1AabNHCupeiLM65ZR9UStMhJ1vCpyV4XbZdyhMZBiJXALQtmn9p42VTQckoHVn8WNqS7dqnJokZHAHcHGoaQgmv8D45oNUKx6DZMNZBCd";
+ let mock_pb_hex = "0a0207902208e1b9de559665c6714080c49789bb2c5aae01081f12a9010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e747261637412740a1541ad8593979840130d222238380b080808080808081215410d292c98a5eca06c2085fff993996423cf66c93b2244a9059cbb0000000000000000000000009bbce520d984c3b95ad10cb4e32a9294e6338da300000000000000000000000000000000000000000000000000000000000f424070c0b6e087bb2c90018094ebdc03";
+ let sign_data = hex::decode(mock_pb_hex).unwrap();
+
+ let result = check_tx_request(&sign_data, &path, xpub);
+ // This should fail because xfp doesn't match but we're testing the decoding works
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_check_tx_request_invalid_address() {
+ let path = "m/44'/195'/0'/0/0".to_string();
+ let xpub = "xpub6C3ndD75jvoARyqUBTvrsMZaprs2ZRF84kRTt5r9oxKQXn5oFChRRgrP2J8QhykhKACBLF2HxwAh4wccFqFsuJUBBcwyvkyqfzJU5gfn5pY";
+ let mock_pb_hex = "0a0207902208e1b9de559665c6714080c49789bb2c5aae01081f12a9010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e747261637412740a1541ad8593979840130d222238380b080808080808081215410d292c98a5eca06c2085fff993996423cf66c93b2244a9059cbb0000000000000000000000009bbce520d984c3b95ad10cb4e32a9294e6338da300000000000000000000000000000000000000000000000000000000000f424070c0b6e087bb2c90018094ebdc03";
+ let sign_data = hex::decode(mock_pb_hex).unwrap();
+
+ let result = check_tx_request(&sign_data, &path, xpub);
+ assert!(result.is_err());
+ assert!(matches!(result.unwrap_err(), TronError::NoMyInputs));
+ }
+
+ #[test]
+ fn test_sign_personal_message() {
+ let path = "m/44'/195'/0'/0/0".to_string();
+ let message = b"Hello TRON";
+ let seed = hex::decode("5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4").unwrap();
+
+ let result = sign_personal_message(message, &path, &seed);
+ assert!(result.is_ok());
+ let sig = result.unwrap();
+ assert_eq!(sig.len(), 130); // 65 bytes * 2 hex chars
+ }
+
+ #[test]
+ fn test_parse_personal_message_utf8() {
+ let message = b"Hello TRON";
+ let result = parse_personal_message(message, None);
+ assert!(result.is_ok());
+ let parsed = result.unwrap();
+ assert_eq!(parsed.utf8_message, "Hello TRON");
+ assert_eq!(parsed.raw_message, hex::encode(message));
+ }
+
+ #[test]
+ fn test_parse_personal_message_non_utf8() {
+ let message = &[0xff, 0xfe, 0xfd];
+ let result = parse_personal_message(message, None);
+ assert!(result.is_ok());
+ let parsed = result.unwrap();
+ assert_eq!(parsed.utf8_message, "");
+ assert_eq!(parsed.raw_message, hex::encode(message));
+ }
+
+ #[test]
+ fn test_parse_personal_message_cjk() {
+ let message = "你好世界".as_bytes();
+ let result = parse_personal_message(message, None);
+ assert!(result.is_ok());
+ let parsed = result.unwrap();
+ assert_eq!(parsed.utf8_message, ""); // CJK should be empty
+ assert_eq!(parsed.raw_message, hex::encode(message));
+ }
+
+ #[test]
+ fn test_parse_personal_message_with_pubkey() {
+ let message = b"Test";
+ let pubkey = PublicKey::from_str(
+ "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
+ )
+ .unwrap();
+ let result = parse_personal_message(message, Some(pubkey));
+ assert!(result.is_ok());
+ let parsed = result.unwrap();
+ assert!(parsed.from.is_some());
+ }
+
+ #[test]
+ fn test_decode_to_wrapped_invalid_data() {
+ let invalid_data = &[0xff, 0xfe, 0xfd];
+ let path = "m/44'/195'/0'/0/0".to_string();
+ let result = decode_to_wrapped(invalid_data, path);
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_parse_raw_tx_error_handling() {
+ let hex = "1f8b08000000000000030dcebb4ac3501c807153444a17b553e95482501142ce39f99f4b8b83362d74696cd38897eddca205db60ac22d95db49b4fe0e6e8e4e65bf80a6e3e80a083816ffb965fb552df9ce461666c6b9c67cb4c6757cd5fa75aa95739e283419f85eeb7535b4fe2a3a8bea3710a42748cc729621e60a43cc1c17801a2c03166444bd4dc1ef9006d1f7768db47653e6aad5e578f7f6877a3f7e234dd2499f2331adc4c212ff27eb83c97b3dbb8b8be3798c96568c971ecbac99416e32c84d3416f3ebceb47878bc509b91806a3c9a58e23368be77b6bc4c1dda8760046714cb148b154982949b400ad4a8f92960bc23ae5e20a510bda12c9d2006b0bd2d8148ca582045b0f9fcf8dc6cfd753291cbebdefb73ec6ff42b912d514010000";
+ let pubkey_str = "xpub6C3ndD75jvoARyqUBTvrsMZaprs2ZRF84kRTt5r9oxKQXn5oFChRRgrP2J8QhykhKACBLF2HxwAh4wccFqFsuJUBBcwyvkyqfzJU5gfn5pY";
+ let payload = prepare_payload(hex);
+ let context = prepare_parse_context(pubkey_str);
+
+ // Should succeed for normal payload
+ let result = parse_raw_tx(payload, context);
+ assert!(result.is_ok());
+ }
+
+ #[test]
+ fn test_check_raw_tx_error_paths() {
+ // Test with mismatched fingerprint
+ let hex = "1f8b08000000000000030dcfbd4ac34000c071220ea58bdaa9742a41a84bc87d27270e9ab61890c4268d54bb5dee2e26607b508b4a9fa26fe01bf8b128f812be82b383b8161703ffe9bffd1a5bad9d64d1374a77470bb334d2dc7436567d1b1e96540920ec6fabb99da5e7716b5f4a4e58ae91e36b221d8272ed088ca04399a058f8b2a09075f62297909e0b39edb9a0ce05dde79faf8f0d3868048f56c7ce2e86d3b13abb35833089f4f4be2a97ca04554cd8eaa13c9d5ca9d0b6b3315d8d4c9f5c0e83597837884fe6f309ba0e719494328d5995ce90050fe3e671c17c0ab9d2bc904011a031a502f202e414032e19c60c78be209e409aab1cfa9041e603c204821ad588ddd7f5baddfefd7c7aff03e1cbdbd13f2aab0f710f010000";
+ let pubkey_str = "xpub6D1AabNHCupeiLM65ZR9UStMhJ1vCpyV4XbZdyhMZBiJXALQtmn9p42VTQckoHVn8WNqS7dqnJokZHAHcHGoaQgmv8D45oNUKx6DZMNZBCd";
+ let payload = prepare_payload(hex);
+
+ // Wrong fingerprint
+ let wrong_fp = bitcoin::bip32::Fingerprint::from_str("00000000").unwrap();
+ let xpub = bitcoin::bip32::Xpub::from_str(pubkey_str).unwrap();
+ let wrong_context = keystone::ParseContext::new(wrong_fp, xpub);
+
+ let result = check_raw_tx(payload, wrong_context);
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_sign_tx_request_error_paths() {
+ let path = "m/44'/195'/0'/0/0".to_string();
+
+ // Invalid protobuf data
+ let invalid_data = vec![0xff, 0xfe, 0xfd];
+ let seed = hex::decode("5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4").unwrap();
+
+ let result = sign_tx_request(&invalid_data, &path, &seed);
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_parse_tx_request_error_paths() {
+ let path = "m/44'/195'/0'/0/0".to_string();
+
+ // Invalid protobuf data
+ let invalid_data = vec![0xff, 0xfe, 0xfd];
+
+ let result = parse_tx_request(&invalid_data, &path);
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_check_tx_request_error_paths() {
+ let path = "m/44'/195'/0'/0/0";
+ let xpub = "xpub6D1AabNHCupeiLM65ZR9UStMhJ1vCpyV4XbZdyhMZBiJXALQtmn9p42VTQckoHVn8WNqS7dqnJokZHAHcHGoaQgmv8D45oNUKx6DZMNZBCd";
+
+ // Invalid protobuf data
+ let invalid_data = vec![0xff, 0xfe, 0xfd];
+
+ let result = check_tx_request(&invalid_data, path, xpub);
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_sign_personal_message_empty() {
+ let path = "m/44'/195'/0'/0/0".to_string();
+ let message = b"";
+ let seed = hex::decode("5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4").unwrap();
+
+ let result = sign_personal_message(message, &path, &seed);
+ assert!(result.is_ok());
+ let sig = result.unwrap();
+ assert_eq!(sig.len(), 130);
+ }
+
+ #[test]
+ fn test_sign_personal_message_long() {
+ let path = "m/44'/195'/0'/0/0".to_string();
+ let message = b"This is a very long message that contains a lot of text to test the signing functionality with longer input data. It should still work correctly and produce a valid signature.";
+ let seed = hex::decode("5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4").unwrap();
+
+ let result = sign_personal_message(message, &path, &seed);
+ assert!(result.is_ok());
+ let sig = result.unwrap();
+ assert_eq!(sig.len(), 130);
+ }
+
+ #[test]
+ fn test_parse_personal_message_empty() {
+ let message = b"";
+ let result = parse_personal_message(message, None);
+ assert!(result.is_ok());
+ let parsed = result.unwrap();
+ assert_eq!(parsed.utf8_message, "");
+ assert_eq!(parsed.raw_message, "");
+ }
+
+ #[test]
+ fn test_parse_personal_message_mixed_content() {
+ // Mix of ASCII and special characters
+ let message = b"Hello@#$%^&*()_+{}[]|";
+ let result = parse_personal_message(message, None);
+ assert!(result.is_ok());
+ let parsed = result.unwrap();
+ assert!(!parsed.raw_message.is_empty());
+ }
+
+ #[test]
+ fn test_get_address_integration() {
+ let path = "m/44'/195'/0'/0/0".to_string();
+ let xpub = "xpub6D1AabNHCupeiLM65ZR9UStMhJ1vCpyV4XbZdyhMZBiJXALQtmn9p42VTQckoHVn8WNqS7dqnJokZHAHcHGoaQgmv8D45oNUKx6DZMNZBCd";
+
+ let result = get_address(path, &xpub.to_string());
+ assert!(result.is_ok());
+ let address = result.unwrap();
+ assert!(address.starts_with("T"));
+ assert!(address.len() == 34); // TRON addresses are 34 chars
+ }
+
+ #[test]
+ fn test_get_address_invalid_path() {
+ let invalid_path = "invalid/path".to_string();
+ let xpub = "xpub6D1AabNHCupeiLM65ZR9UStMhJ1vCpyV4XbZdyhMZBiJXALQtmn9p42VTQckoHVn8WNqS7dqnJokZHAHcHGoaQgmv8D45oNUKx6DZMNZBCd";
+
+ let result = get_address(invalid_path, &xpub.to_string());
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_get_address_invalid_xpub() {
+ let path = "m/44'/195'/0'/0/0".to_string();
+ let invalid_xpub = "invalid_xpub";
+
+ let result = get_address(path, &invalid_xpub.to_string());
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_decode_to_wrapped_empty_raw_data() {
+ use crate::pb::protocol::transaction::Raw as RawData;
+ use prost::Message;
+
+ // Create valid but minimal protobuf data
+ let raw = RawData::default();
+ let encoded = raw.encode_to_vec();
+ let path = "m/44'/195'/0'/0/0".to_string();
+
+ let result = decode_to_wrapped(&encoded, path);
+ assert!(result.is_ok());
+ }
}
diff --git a/rust/apps/tron/src/structs.rs b/rust/apps/tron/src/structs.rs
index 34c032c..4b9822c 100644
--- a/rust/apps/tron/src/structs.rs
+++ b/rust/apps/tron/src/structs.rs
@@ -32,12 +32,8 @@ mod tests {
#[test]
fn test_personal_message_without_from() {
- let msg = PersonalMessage::from(
- "0x48656c6c6f".to_string(),
- "Hello".to_string(),
- None,
- )
- .unwrap();
+ let msg =
+ PersonalMessage::from("0x48656c6c6f".to_string(), "Hello".to_string(), None).unwrap();
assert_eq!(msg.raw_message, "0x48656c6c6f");
assert_eq!(msg.utf8_message, "Hello");
diff --git a/rust/apps/tron/src/transaction/wrapped_tron.rs b/rust/apps/tron/src/transaction/wrapped_tron.rs
index 6cf80e0..db55759 100644
--- a/rust/apps/tron/src/transaction/wrapped_tron.rs
+++ b/rust/apps/tron/src/transaction/wrapped_tron.rs
@@ -741,4 +741,147 @@ mod tests {
TronError::InvalidParseContext(_)
));
}
+
+ #[test]
+ fn test_format_amount_small_values() {
+ let hex = "1f8b08000000000000030dcfbd4ac34000c071220ea58bdaa9742a41a84bc87d27270e9ab61890c4268d54bb5dee2e26607b508b4a9fa26fe01bf8b128f812be82b383b8161703ffe9bffd1a5bad9d64d1374a77470bb334d2dc7436567d1b1e96540920ec6fabb99da5e7716b5f4a4e58ae91e36b221d8272ed088ca04399a058f8b2a09075f62297909e0b39edb9a0ce05dde79faf8f0d3868048f56c7ce2e86d3b13abb35833089f4f4be2a97ca04554cd8eaa13c9d5ca9d0b6b3315d8d4c9f5c0e83597837884fe6f309ba0e719494328d5995ce90050fe3e671c17c0ab9d2bc904011a031a502f202e414032e19c60c78be209e409aab1cfa9041e603c204821ad588ddd7f5baddfefd7c7aff03e1cbdbd13f2aab0f710f010000";
+ let pubkey_str = "xpub6D1AabNHCupeiLM65ZR9UStMhJ1vCpyV4XbZdyhMZBiJXALQtmn9p42VTQckoHVn8WNqS7dqnJokZHAHcHGoaQgmv8D45oNUKx6DZMNZBCd";
+ let payload = prepare_payload(hex);
+ let context = prepare_parse_context(pubkey_str);
+ let mut tx = WrappedTron::from_payload(payload, &context).unwrap();
+
+ // Test with value 1 (smallest non-zero)
+ tx.value = "1".to_string();
+ let formatted = tx.format_amount().unwrap();
+ assert!(formatted.contains("0.000001"));
+
+ // Test with zero value
+ tx.value = "0".to_string();
+ let formatted = tx.format_amount().unwrap();
+ assert!(formatted.starts_with("0"));
+ }
+
+ #[test]
+ fn test_format_amount_various_decimals() {
+ let hex = "1f8b08000000000000031590bf4ac3501c46359452bba871299d4a102a42c8bffbbbf7c6499b1403b6b14d52b42e92e426b5c53636462979029d7d01477707279f40147c0007df41707130856f3870a6f355387ebd9f1a098b1abd34c99230b9acbf70158eaf1099b4db26368427ae5af29c639bdf0e98a652d50fc4500922110121a21efb548c028010142d8814bdbed995106a4a8a0e4d492e26c98defb78ffb3f79a7dcfa5ae505cf21b6359f4447fdc5a1678ce99c9e0dd1558726999b8f269d09ceea82e7b96408dab58bd23c358deccc1fdf38f97cc114ec6746a40e1c41f05cc87b89814edbada9756bda07b3d9893ab2b46eff22746c3c76a6bb2b6a49d129d9b3abfb3e8be3400335f4090d3506818c303042402f0c669851888160504286502c2b408b001d01f5fd40d6286c3c7f3ed46a773fef45486bab5a1ab8a6c7af2d6f395f62ad6c3dfee2c66bef1f257dc3fe50010000";
+ let pubkey_str = "xpub6C3ndD75jvoARyqUBTvrsMZaprs2ZRF84kRTt5r9oxKQXn5oFChRRgrP2J8QhykhKACBLF2HxwAh4wccFqFsuJUBBcwyvkyqfzJU5gfn5pY";
+ let payload = prepare_payload(hex);
+ let context = prepare_parse_context(pubkey_str);
+ let mut tx = WrappedTron::from_payload(payload, &context).unwrap();
+
+ // Test 18 decimals (like TUSD)
+ tx.divider = 1_000_000_000_000_000_000.0;
+ tx.value = "1000000000000000000".to_string();
+ let formatted = tx.format_amount().unwrap();
+ assert!(formatted.contains("1"));
+
+ // Test 8 decimals (like WBTC)
+ tx.divider = 100_000_000.0;
+ tx.value = "100000000".to_string();
+ let formatted = tx.format_amount().unwrap();
+ assert!(formatted.contains("1"));
+ }
+
+ #[test]
+ fn test_from_raw_transaction_unknown_contract_type() {
+ let mut tron_tx = Transaction::default();
+ let mut raw = transaction::Raw::default();
+ let mut contract = transaction::Contract::default();
+ contract.r#type = 99; // Unknown contract type
+ contract.parameter = None; // No parameter for unknown type
+ raw.contract = vec![contract];
+ tron_tx.raw_data = Some(raw);
+
+ let result = WrappedTron::from_raw_transaction(tron_tx, "m/44'/195'/0'/0/0".to_string());
+ assert!(result.is_ok());
+ let wrapped = result.unwrap();
+ assert_eq!(wrapped.from, "");
+ assert_eq!(wrapped.to, "");
+ }
+
+ #[test]
+ fn test_from_raw_transaction_trc20_short_data() {
+ let mut tron_tx = Transaction::default();
+ let mut raw = transaction::Raw::default();
+ let mut contract = transaction::Contract::default();
+ contract.r#type = 31; // TriggerSmartContract
+
+ let mut trigger_contract = TriggerSmartContract::default();
+ trigger_contract.owner_address = vec![0x41; 21];
+ trigger_contract.contract_address = vec![0x41; 21];
+ trigger_contract.data = vec![0xa9, 0x05, 0x9c, 0xbb]; // transfer selector but data too short
+
+ contract.parameter = Some(prost_types::Any {
+ type_url: "type.googleapis.com/protocol.TriggerSmartContract".to_string(),
+ value: trigger_contract.encode_to_vec(),
+ });
+ raw.contract = vec![contract];
+ tron_tx.raw_data = Some(raw);
+
+ let result = WrappedTron::from_raw_transaction(tron_tx, "m/44'/195'/0'/0/0".to_string());
+ assert!(result.is_ok());
+ let wrapped = result.unwrap();
+ // Should not parse TRC-20 data if it's too short
+ assert_eq!(wrapped.value, "0");
+ }
+
+ #[test]
+ fn test_from_raw_transaction_trc20_wrong_selector() {
+ let mut tron_tx = Transaction::default();
+ let mut raw = transaction::Raw::default();
+ let mut contract = transaction::Contract::default();
+ contract.r#type = 31;
+
+ let mut trigger_contract = TriggerSmartContract::default();
+ trigger_contract.owner_address = vec![0x41; 21];
+ trigger_contract.contract_address = vec![0x41; 21];
+ trigger_contract.data = vec![0xff; 68]; // Wrong selector, but correct length
+
+ contract.parameter = Some(prost_types::Any {
+ type_url: "type.googleapis.com/protocol.TriggerSmartContract".to_string(),
+ value: trigger_contract.encode_to_vec(),
+ });
+ raw.contract = vec![contract];
+ tron_tx.raw_data = Some(raw);
+
+ let result = WrappedTron::from_raw_transaction(tron_tx, "m/44'/195'/0'/0/0".to_string());
+ assert!(result.is_ok());
+ let wrapped = result.unwrap();
+ assert_eq!(wrapped.value, "0");
+ }
+
+ #[test]
+ fn test_from_raw_transaction_no_contract() {
+ let mut tron_tx = Transaction::default();
+ let mut raw = transaction::Raw::default();
+ raw.contract = vec![]; // No contracts
+ tron_tx.raw_data = Some(raw);
+
+ let result = WrappedTron::from_raw_transaction(tron_tx, "m/44'/195'/0'/0/0".to_string());
+ assert!(result.is_ok());
+ let wrapped = result.unwrap();
+ assert_eq!(wrapped.from, "");
+ assert_eq!(wrapped.value, "0");
+ }
+
+ #[test]
+ fn test_format_amount_edge_cases() {
+ let hex = "1f8b08000000000000030dcfbd4ac34000c071220ea58bdaa9742a41a84bc87d27270e9ab61890c4268d54bb5dee2e26607b508b4a9fa26fe01bf8b128f812be82b383b8161703ffe9bffd1a5bad9d64d1374a77470bb334d2dc7436567d1b1e96540920ec6fabb99da5e7716b5f4a4e58ae91e36b221d8272ed088ca04399a058f8b2a09075f62297909e0b39edb9a0ce05dde79faf8f0d3868048f56c7ce2e86d3b13abb35833089f4f4be2a97ca04554cd8eaa13c9d5ca9d0b6b3315d8d4c9f5c0e83597837884fe6f309ba0e719494328d5995ce90050fe3e671c17c0ab9d2bc904011a031a502f202e414032e19c60c78be209e409aab1cfa9041e603c204821ad588ddd7f5baddfefd7c7aff03e1cbdbd13f2aab0f710f010000";
+ let pubkey_str = "xpub6D1AabNHCupeiLM65ZR9UStMhJ1vCpyV4XbZdyhMZBiJXALQtmn9p42VTQckoHVn8WNqS7dqnJokZHAHcHGoaQgmv8D45oNUKx6DZMNZBCd";
+ let payload = prepare_payload(hex);
+ let context = prepare_parse_context(pubkey_str);
+ let mut tx = WrappedTron::from_payload(payload, &context).unwrap();
+
+ // Test with custom divider (not 6 or 18)
+ tx.divider = 1_000.0; // 3 decimals
+ tx.value = "1000".to_string();
+ let formatted = tx.format_amount().unwrap();
+ assert!(formatted.contains("1"));
+
+ // Test with divider = 1 (no decimals)
+ tx.divider = 1.0;
+ tx.value = "100".to_string();
+ let formatted = tx.format_amount().unwrap();
+ assert!(formatted.contains("100"));
+ }
}
Why this scored 14/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.