1#![warn(
6 future_incompatible,
7 nonstandard_style,
8 rust_2018_idioms,
9 rust_2021_compatibility
10)]
11
12use iota_sdk_types::{Address, ObjectId, StructTag, TypeTag, Version};
13use move_binary_format::{
14 CompiledModule,
15 file_format::{AbilitySet, SignatureToken},
16};
17use move_bytecode_utils::resolve_struct;
18use move_core_types::{account_address::AccountAddress, language_storage::ModuleId};
19use object::OBJECT_START_VERSION;
20
21use crate::{
22 base_types::{RESOLVED_ASCII_STR, RESOLVED_STD_OPTION, RESOLVED_UTF8_STR},
23 id::RESOLVED_IOTA_ID,
24 iota_sdk_types_conversions::{struct_tag_core_to_sdk, type_tag_core_to_sdk},
25};
26
27#[macro_use]
28pub mod error;
29
30pub mod account_abstraction;
31pub mod auth_context;
32pub mod balance;
33pub mod base_types;
34pub mod clock;
35pub mod coin;
36pub mod coin_manager;
37pub mod collection_types;
38pub mod committee;
39pub mod config;
40pub mod crypto;
41pub mod deny_list_v1;
42pub mod deny_rule_governance;
43pub mod digests;
44pub mod display;
45pub mod dynamic_field;
46pub mod effects;
47pub mod epoch_data;
48pub mod event;
49pub mod executable_transaction;
50pub mod execution;
51pub mod execution_config_utils;
52pub mod full_checkpoint_content;
53pub mod gas;
54pub mod gas_coin;
55pub mod gas_model;
56pub mod global_state_hash;
57pub mod governance;
58pub mod id;
59pub mod in_memory_storage;
60pub mod inner_temporary_store;
61pub mod iota_sdk_types_conversions;
62pub mod iota_serde;
63pub mod iota_system_state;
64pub mod layout_resolver;
65pub mod message_envelope;
66pub mod messages_checkpoint;
67#[cfg(not(target_arch = "wasm32"))]
70pub mod messages_consensus;
71#[cfg(not(target_arch = "wasm32"))]
72pub mod messages_grpc;
73pub mod messages_safe_client;
74pub mod metrics;
75pub mod mock_checkpoint_builder;
76pub mod move_authenticator;
77pub mod move_package;
78pub mod multisig;
79pub mod object;
80pub mod passkey_authenticator;
81pub mod programmable_transaction_builder;
82pub mod proto_value;
83pub mod quorum_driver_types;
84pub mod randomness_state;
85pub mod signature;
86pub mod signature_verification;
87pub mod stardust;
88pub mod storage;
89pub mod supported_protocol_versions;
90pub mod system_admin_cap;
91pub mod test_checkpoint_data_builder;
92pub mod timelock;
93pub mod traffic_control;
94pub mod transaction;
95pub mod transaction_deny_rules;
96pub mod transaction_driver_types;
97pub mod transaction_executor;
98pub mod transfer;
99pub mod versioned;
100
101#[path = "./unit_tests/utils.rs"]
102pub mod utils;
103
104macro_rules! built_in_ids {
105 ($($addr:ident / $id:ident = $init:expr);* $(;)?) => {
106 $(
107 pub const $addr: AccountAddress = builtin_address($init);
108 pub const $id: ObjectId = ObjectId::new($addr.into_bytes());
109 )*
110 }
111}
112
113macro_rules! built_in_pkgs {
114 ($($addr:ident / $id:ident = $init:expr);* $(;)?) => {
115 built_in_ids! { $($addr / $id = $init;)* }
116 }
117}
118
119built_in_pkgs! {
120 MOVE_STDLIB_ADDRESS / MOVE_STDLIB_PACKAGE_ID = 0x1;
121 IOTA_FRAMEWORK_ADDRESS / IOTA_FRAMEWORK_PACKAGE_ID = 0x2;
122 IOTA_SYSTEM_ADDRESS / IOTA_SYSTEM_PACKAGE_ID = 0x3;
123 GENESIS_BRIDGE_ADDRESS / GENESIS_BRIDGE_PACKAGE_ID = 0xb;
124 STARDUST_ADDRESS / STARDUST_PACKAGE_ID = 0x107a;
125}
126
127built_in_ids! {
128 IOTA_SYSTEM_STATE_ADDRESS / IOTA_SYSTEM_STATE_OBJECT_ID = 0x5;
129 IOTA_CLOCK_ADDRESS / IOTA_CLOCK_OBJECT_ID = 0x6;
130 IOTA_AUTHENTICATOR_STATE_ADDRESS / IOTA_AUTHENTICATOR_STATE_OBJECT_ID = 0x7;
131 IOTA_RANDOMNESS_STATE_ADDRESS / IOTA_RANDOMNESS_STATE_OBJECT_ID = 0x8;
132 GENESIS_IOTA_BRIDGE_ADDRESS / GENESIS_IOTA_BRIDGE_OBJECT_ID = 0x9;
133 IOTA_DENY_LIST_ADDRESS / IOTA_DENY_LIST_OBJECT_ID = 0x403;
134 IOTA_TRANSACTION_DENY_RULES_ADDRESS / IOTA_TRANSACTION_DENY_RULES_OBJECT_ID = 0xde9;
135}
136
137pub const SYSTEM_PACKAGE_ADDRESSES: [Address; 5] = [
138 Address::STD,
139 Address::FRAMEWORK,
140 Address::SYSTEM,
141 Address::GENESIS_BRIDGE,
142 Address::STARDUST,
143];
144
145pub const IOTA_SYSTEM_STATE_OBJECT_SHARED_VERSION: Version = OBJECT_START_VERSION;
146pub const IOTA_CLOCK_OBJECT_SHARED_VERSION: Version = OBJECT_START_VERSION;
147
148const fn builtin_address(suffix: u16) -> AccountAddress {
149 let mut addr = [0u8; AccountAddress::LENGTH];
150 let [hi, lo] = suffix.to_be_bytes();
151 addr[AccountAddress::LENGTH - 2] = hi;
152 addr[AccountAddress::LENGTH - 1] = lo;
153 AccountAddress::new(addr)
154}
155
156pub fn iota_framework_address_concat_string(suffix: &str) -> String {
157 format!("{}{suffix}", Address::FRAMEWORK.to_short_hex())
158}
159
160pub fn parse_iota_address(s: &str) -> anyhow::Result<Address> {
171 use move_core_types::parsing::address::ParsedAddress;
172 Ok(Address::new(
173 ParsedAddress::parse(s)?
174 .into_account_address(&resolve_address)?
175 .into_bytes(),
176 ))
177}
178
179pub fn parse_iota_module_id(s: &str) -> anyhow::Result<ModuleId> {
184 use move_core_types::parsing::types::ParsedModuleId;
185 ParsedModuleId::parse(s)?.into_module_id(&resolve_address)
186}
187
188pub fn parse_iota_fq_name(s: &str) -> anyhow::Result<(ModuleId, String)> {
194 use move_core_types::parsing::types::ParsedFqName;
195 ParsedFqName::parse(s)?.into_fq_name(&resolve_address)
196}
197
198pub fn parse_iota_struct_tag(s: &str) -> anyhow::Result<StructTag> {
204 use move_core_types::parsing::types::ParsedStructType;
205 ParsedStructType::parse(s)?
206 .into_struct_tag(&resolve_address)
207 .map(|s| struct_tag_core_to_sdk(&s))
208}
209
210pub fn parse_iota_type_tag(s: &str) -> anyhow::Result<TypeTag> {
215 use move_core_types::parsing::types::ParsedType;
216 ParsedType::parse(s)?
217 .into_type_tag(&resolve_address)
218 .map(|s| type_tag_core_to_sdk(&s))
219}
220
221pub fn resolve_address(addr: &str) -> Option<AccountAddress> {
223 match addr {
224 "std" => Some(Address::STD),
225 "iota" => Some(Address::FRAMEWORK),
226 "iota_system" => Some(Address::SYSTEM),
227 "stardust" => Some(Address::STARDUST),
228 _ => None,
229 }
230 .map(|addr| AccountAddress::new(addr.into_bytes()))
231}
232
233pub trait MoveTypeTagTrait {
234 fn get_type_tag() -> TypeTag;
235}
236
237impl MoveTypeTagTrait for u8 {
238 fn get_type_tag() -> TypeTag {
239 TypeTag::U8
240 }
241}
242
243impl MoveTypeTagTrait for u64 {
244 fn get_type_tag() -> TypeTag {
245 TypeTag::U64
246 }
247}
248
249impl MoveTypeTagTrait for String {
250 fn get_type_tag() -> TypeTag {
251 TypeTag::Struct(Box::new(StructTag::new_string()))
252 }
253}
254
255impl MoveTypeTagTrait for ObjectId {
256 fn get_type_tag() -> TypeTag {
257 TypeTag::Address
258 }
259}
260
261impl MoveTypeTagTrait for Address {
262 fn get_type_tag() -> TypeTag {
263 TypeTag::Address
264 }
265}
266
267impl<T: MoveTypeTagTrait> MoveTypeTagTrait for Vec<T> {
268 fn get_type_tag() -> TypeTag {
269 TypeTag::Vector(Box::new(T::get_type_tag()))
270 }
271}
272
273pub fn is_primitive(
276 view: &CompiledModule,
277 function_type_args: &[AbilitySet],
278 s: &SignatureToken,
279) -> bool {
280 is_primitive_inner(view, function_type_args, s, false)
281}
282
283pub fn is_primitive_strict(
286 view: &CompiledModule,
287 function_type_args: &[AbilitySet],
288 s: &SignatureToken,
289) -> bool {
290 is_primitive_inner(view, function_type_args, s, true)
291}
292
293pub fn is_primitive_inner(
299 view: &CompiledModule,
300 function_type_args: &[AbilitySet],
301 s: &SignatureToken,
302 is_strict: bool,
303) -> bool {
304 use SignatureToken as S;
305 match s {
306 S::Bool | S::U8 | S::U16 | S::U32 | S::U64 | S::U128 | S::U256 | S::Address => true,
307 S::Signer => false,
308 S::TypeParameter(idx) => {
311 if !is_strict {
312 !function_type_args[*idx as usize].has_key()
314 } else {
315 let abilities = function_type_args[*idx as usize];
318 !abilities.has_key() && (abilities.has_copy() || abilities.has_drop())
319 }
320 }
321
322 S::Datatype(idx) => [RESOLVED_IOTA_ID, RESOLVED_ASCII_STR, RESOLVED_UTF8_STR]
323 .contains(&resolve_struct(view, *idx)),
324
325 S::DatatypeInstantiation(inst) => {
326 let (idx, targs) = &**inst;
327 let resolved_struct = resolve_struct(view, *idx);
328 resolved_struct == RESOLVED_STD_OPTION
330 && targs.len() == 1
331 && is_primitive_inner(view, function_type_args, &targs[0], is_strict)
332 }
333
334 S::Vector(inner) => is_primitive_inner(view, function_type_args, inner, is_strict),
335 S::Reference(_) | S::MutableReference(_) => false,
336 }
337}
338
339pub fn is_object(
340 view: &CompiledModule,
341 function_type_args: &[AbilitySet],
342 t: &SignatureToken,
343) -> Result<bool, String> {
344 use SignatureToken as S;
345 match t {
346 S::Reference(inner) | S::MutableReference(inner) => {
347 is_object(view, function_type_args, inner)
348 }
349 _ => is_object_struct(view, function_type_args, t),
350 }
351}
352
353pub fn is_object_vector(
354 view: &CompiledModule,
355 function_type_args: &[AbilitySet],
356 t: &SignatureToken,
357) -> Result<bool, String> {
358 use SignatureToken as S;
359 match t {
360 S::Vector(inner) => is_object_struct(view, function_type_args, inner),
361 _ => is_object_struct(view, function_type_args, t),
362 }
363}
364
365pub fn is_object_struct(
366 view: &CompiledModule,
367 function_type_args: &[AbilitySet],
368 s: &SignatureToken,
369) -> Result<bool, String> {
370 use SignatureToken as S;
371 match s {
372 S::Bool
373 | S::U8
374 | S::U16
375 | S::U32
376 | S::U64
377 | S::U128
378 | S::U256
379 | S::Address
380 | S::Signer
381 | S::Vector(_)
382 | S::Reference(_)
383 | S::MutableReference(_) => Ok(false),
384 S::TypeParameter(idx) => Ok(function_type_args
385 .get(*idx as usize)
386 .map(|abs| abs.has_key())
387 .unwrap_or(false)),
388 S::Datatype(_) | S::DatatypeInstantiation(_) => {
389 let abilities = view
390 .abilities(s, function_type_args)
391 .map_err(|vm_err| vm_err.to_string())?;
392 Ok(abilities.has_key())
393 }
394 }
395}
396
397#[cfg(test)]
398mod tests {
399 use expect_test::expect;
400
401 use super::*;
402
403 #[test]
404 fn test_parse_iota_numeric_address() {
405 let result = parse_iota_address("0x2").expect("should not error");
406
407 let expected =
408 expect!["0x0000000000000000000000000000000000000000000000000000000000000002"];
409 expected.assert_eq(&result.to_string());
410 }
411
412 #[test]
413 fn test_parse_iota_named_address() {
414 let result = parse_iota_address("iota").expect("should not error");
415
416 let expected =
417 expect!["0x0000000000000000000000000000000000000000000000000000000000000002"];
418 expected.assert_eq(&result.to_string());
419 }
420
421 #[test]
422 fn test_parse_iota_module_id() {
423 let result = parse_iota_module_id("0x2::iota").expect("should not error");
424 let expected =
425 expect!["0x0000000000000000000000000000000000000000000000000000000000000002::iota"];
426 expected.assert_eq(&result.to_canonical_string(true));
427 }
428
429 #[test]
430 fn test_parse_iota_fq_name() {
431 let (module, name) = parse_iota_fq_name("0x2::object::new").expect("should not error");
432 let expected = expect![
433 "0x0000000000000000000000000000000000000000000000000000000000000002::object::new"
434 ];
435 expected.assert_eq(&format!(
436 "{}::{name}",
437 module.to_canonical_display(true)
438 ));
439 }
440
441 #[test]
442 fn test_parse_iota_struct_tag_short_account_addr() {
443 let result = parse_iota_struct_tag("0x2::iota::IOTA").expect("should not error");
444
445 let expected = expect!["0x2::iota::IOTA"];
446 expected.assert_eq(&result.to_string());
447
448 let expected = expect![
449 "0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA"
450 ];
451 expected.assert_eq(&result.to_canonical_string(true));
452 }
453
454 #[test]
455 fn test_parse_iota_struct_tag_long_account_addr() {
456 let result = parse_iota_struct_tag(
457 "0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA",
458 )
459 .expect("should not error");
460
461 let expected = expect!["0x2::iota::IOTA"];
462 expected.assert_eq(&result.to_string());
463
464 let expected = expect![
465 "0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA"
466 ];
467 expected.assert_eq(&result.to_canonical_string(true));
468 }
469
470 #[test]
471 fn test_parse_iota_struct_with_type_param_short_addr() {
472 let result =
473 parse_iota_struct_tag("0x2::coin::COIN<0x2::iota::IOTA>").expect("should not error");
474
475 let expected = expect!["0x2::coin::COIN<0x2::iota::IOTA>"];
476 expected.assert_eq(&result.to_string());
477
478 let expected = expect![
479 "0x0000000000000000000000000000000000000000000000000000000000000002::coin::COIN<0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA>"
480 ];
481 expected.assert_eq(&result.to_canonical_string(true));
482 }
483
484 #[test]
485 fn test_parse_iota_struct_with_type_param_long_addr() {
486 let result = parse_iota_struct_tag("0x0000000000000000000000000000000000000000000000000000000000000002::coin::COIN<0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA>")
487 .expect("should not error");
488
489 let expected = expect!["0x2::coin::COIN<0x2::iota::IOTA>"];
490 expected.assert_eq(&result.to_string());
491
492 let expected = expect![
493 "0x0000000000000000000000000000000000000000000000000000000000000002::coin::COIN<0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA>"
494 ];
495 expected.assert_eq(&result.to_canonical_string(true));
496 }
497
498 #[test]
499 fn test_complex_struct_tag_with_short_addr() {
500 let result = parse_iota_struct_tag(
501 "0xe7::vec_coin::VecCoin<vector<0x2::coin::Coin<0x2::iota::IOTA>>>",
502 )
503 .expect("should not error");
504
505 let expected = expect!["0xe7::vec_coin::VecCoin<vector<0x2::coin::Coin<0x2::iota::IOTA>>>"];
506 expected.assert_eq(&result.to_string());
507
508 let expected = expect![
509 "0x00000000000000000000000000000000000000000000000000000000000000e7::vec_coin::VecCoin<vector<0x0000000000000000000000000000000000000000000000000000000000000002::coin::Coin<0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA>>>"
510 ];
511 expected.assert_eq(&result.to_canonical_string(true));
512 }
513
514 #[test]
515 fn test_complex_struct_tag_with_long_addr() {
516 let result = parse_iota_struct_tag("0x00000000000000000000000000000000000000000000000000000000000000e7::vec_coin::VecCoin<vector<0x0000000000000000000000000000000000000000000000000000000000000002::coin::Coin<0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA>>>")
517 .expect("should not error");
518
519 let expected = expect!["0xe7::vec_coin::VecCoin<vector<0x2::coin::Coin<0x2::iota::IOTA>>>"];
520 expected.assert_eq(&result.to_string());
521
522 let expected = expect![
523 "0x00000000000000000000000000000000000000000000000000000000000000e7::vec_coin::VecCoin<vector<0x0000000000000000000000000000000000000000000000000000000000000002::coin::Coin<0x0000000000000000000000000000000000000000000000000000000000000002::iota::IOTA>>>"
524 ];
525 expected.assert_eq(&result.to_canonical_string(true));
526 }
527
528 #[test]
529 fn test_dynamic_field_short_addr() {
530 let result = parse_iota_struct_tag(
531 "0x2::dynamic_field::Field<address, 0x2::balance::Balance<0x234::coin::COIN>>",
532 )
533 .expect("should not error");
534
535 let expected =
536 expect!["0x2::dynamic_field::Field<address, 0x2::balance::Balance<0x234::coin::COIN>>"];
537 expected.assert_eq(&result.to_string());
538
539 let expected = expect![
540 "0x0000000000000000000000000000000000000000000000000000000000000002::dynamic_field::Field<address,0x0000000000000000000000000000000000000000000000000000000000000002::balance::Balance<0x0000000000000000000000000000000000000000000000000000000000000234::coin::COIN>>"
541 ];
542 expected.assert_eq(&result.to_canonical_string(true));
543 }
544
545 #[test]
546 fn test_dynamic_field_long_addr() {
547 let result = parse_iota_struct_tag(
548 "0x2::dynamic_field::Field<address, 0x2::balance::Balance<0x234::coin::COIN>>",
549 )
550 .expect("should not error");
551
552 let expected =
553 expect!["0x2::dynamic_field::Field<address, 0x2::balance::Balance<0x234::coin::COIN>>"];
554 expected.assert_eq(&result.to_string());
555
556 let expected = expect![
557 "0x0000000000000000000000000000000000000000000000000000000000000002::dynamic_field::Field<address,0x0000000000000000000000000000000000000000000000000000000000000002::balance::Balance<0x0000000000000000000000000000000000000000000000000000000000000234::coin::COIN>>"
558 ];
559 expected.assert_eq(&result.to_canonical_string(true));
560 }
561}