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