1#![warn(
4 future_incompatible,
5 nonstandard_style,
6 rust_2018_idioms,
7 rust_2021_compatibility
8)]
9
10use base_types::{SequenceNumber, SuiAddress};
11use move_binary_format::CompiledModule;
12use move_binary_format::file_format::{AbilitySet, SignatureToken};
13use move_bytecode_utils::resolve_struct;
14use move_core_types::language_storage::ModuleId;
15use move_core_types::{account_address::AccountAddress, language_storage::StructTag};
16pub use move_core_types::{identifier::Identifier, language_storage::TypeTag};
17use object::OBJECT_START_VERSION;
18
19use base_types::ObjectID;
20
21pub use mysten_network::multiaddr;
22
23use crate::base_types::{RESOLVED_ASCII_STR, RESOLVED_UTF8_STR};
24use crate::{base_types::RESOLVED_STD_OPTION, id::RESOLVED_SUI_ID};
25
26#[macro_use]
27pub mod error;
28pub mod accumulator_event;
29pub mod accumulator_metadata;
30pub mod accumulator_root;
31pub mod address_alias;
32pub mod allowance;
33pub mod authenticator_state;
34pub mod balance;
35pub mod balance_change;
36pub mod base_types;
37pub mod bridge;
38pub mod clock;
39pub mod coin;
40pub mod coin_registry;
41pub mod coin_reservation;
42pub mod collection_types;
43pub mod committee;
44pub mod config;
45pub mod crypto;
46pub mod deny_list_v1;
47pub mod deny_list_v2;
48pub mod derived_object;
49pub mod digests;
50pub mod display;
51pub mod display_registry;
52pub mod dynamic_field;
53pub mod effects;
54pub mod epoch_data;
55pub mod event;
56pub mod executable_transaction;
57pub mod execution;
58pub mod execution_params;
59pub mod execution_status;
60pub mod full_checkpoint_content;
61pub mod funds_accumulator;
62pub mod gas;
63pub mod gas_coin;
64pub mod gas_model;
65pub mod global_state_hash;
66pub mod governance;
67pub mod id;
68pub mod in_memory_storage;
69pub mod inner_temporary_store;
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 move_package;
78pub mod multisig;
79pub mod multisig_legacy;
80pub mod nitro_attestation;
81pub mod node_role;
82pub mod object;
83pub mod passkey_authenticator;
84pub mod programmable_transaction_builder;
85pub mod ptb_trace;
86pub mod randomness_state;
87pub mod rpc_proto_conversions;
88pub mod signature;
89pub mod signature_verification;
90pub mod storage;
91pub mod sui_sdk_types_conversions;
92pub mod sui_serde;
93pub mod sui_system_state;
94pub mod supported_protocol_versions;
95pub mod test_checkpoint_data_builder;
96pub mod traffic_control;
97pub mod transaction;
98pub mod transaction_deny_rules;
99pub mod transaction_driver_types;
100pub mod transaction_executor;
101pub mod transfer;
102pub mod type_input;
103pub mod versioned;
104pub mod zk_login_authenticator;
105pub mod zk_login_util;
106
107#[path = "./unit_tests/utils.rs"]
108pub mod utils;
109
110macro_rules! built_in_ids {
111 ($($addr:ident / $id:ident = $init:expr);* $(;)?) => {
112 $(
113 pub const $addr: AccountAddress = AccountAddress::from_suffix($init);
114 pub const $id: ObjectID = ObjectID::from_address($addr);
115 )*
116 }
117}
118
119macro_rules! built_in_pkgs {
120 ($($addr:ident / $id:ident = $init:expr);* $(;)?) => {
121 built_in_ids! { $($addr / $id = $init;)* }
122 pub const SYSTEM_PACKAGE_ADDRESSES: &[AccountAddress] = &[$($addr),*];
123 pub fn is_system_package(addr: impl Into<AccountAddress>) -> bool {
124 matches!(addr.into(), $($addr)|*)
125 }
126 }
127}
128
129built_in_pkgs! {
130 MOVE_STDLIB_ADDRESS / MOVE_STDLIB_PACKAGE_ID = 0x1;
131 SUI_FRAMEWORK_ADDRESS / SUI_FRAMEWORK_PACKAGE_ID = 0x2;
132 SUI_SYSTEM_ADDRESS / SUI_SYSTEM_PACKAGE_ID = 0x3;
133 BRIDGE_ADDRESS / BRIDGE_PACKAGE_ID = 0xb;
134 DEEPBOOK_ADDRESS / DEEPBOOK_PACKAGE_ID = 0xdee9;
135}
136
137built_in_ids! {
138 SUI_SYSTEM_STATE_ADDRESS / SUI_SYSTEM_STATE_OBJECT_ID = 0x5;
139 SUI_CLOCK_ADDRESS / SUI_CLOCK_OBJECT_ID = 0x6;
140 SUI_AUTHENTICATOR_STATE_ADDRESS / SUI_AUTHENTICATOR_STATE_OBJECT_ID = 0x7;
141 SUI_RANDOMNESS_STATE_ADDRESS / SUI_RANDOMNESS_STATE_OBJECT_ID = 0x8;
142 SUI_BRIDGE_ADDRESS / SUI_BRIDGE_OBJECT_ID = 0x9;
143 SUI_COIN_REGISTRY_ADDRESS / SUI_COIN_REGISTRY_OBJECT_ID = 0xc;
144 SUI_DISPLAY_REGISTRY_ADDRESS / SUI_DISPLAY_REGISTRY_OBJECT_ID = 0xd;
145 SUI_DENY_LIST_ADDRESS / SUI_DENY_LIST_OBJECT_ID = 0x403;
146 SUI_ACCUMULATOR_ROOT_ADDRESS / SUI_ACCUMULATOR_ROOT_OBJECT_ID = 0xacc;
147 SUI_ADDRESS_ALIAS_STATE_ADDRESS / SUI_ADDRESS_ALIAS_STATE_OBJECT_ID = 0xa;
148 SUI_FORWARDING_ADDRESS_REGISTRY_ADDRESS / SUI_FORWARDING_ADDRESS_REGISTRY_OBJECT_ID = 0xfa;
149}
150
151pub const SUI_SYSTEM_STATE_OBJECT_SHARED_VERSION: SequenceNumber = OBJECT_START_VERSION;
152pub const SUI_CLOCK_OBJECT_SHARED_VERSION: SequenceNumber = OBJECT_START_VERSION;
153
154pub const IMPLICITLY_READ_SYSTEM_OBJECTS: &[ObjectID] = &[
167 SUI_ACCUMULATOR_ROOT_OBJECT_ID,
168 SUI_FORWARDING_ADDRESS_REGISTRY_OBJECT_ID,
169];
170
171pub fn sui_framework_address_concat_string(suffix: &str) -> String {
172 format!("{}{suffix}", SUI_FRAMEWORK_ADDRESS.to_hex_literal())
173}
174
175pub fn parse_sui_address(s: &str) -> anyhow::Result<SuiAddress> {
183 use move_core_types::parsing::address::ParsedAddress;
184 Ok(ParsedAddress::parse(s)?
185 .into_account_address(&resolve_address)?
186 .into())
187}
188
189pub fn parse_sui_module_id(s: &str) -> anyhow::Result<ModuleId> {
193 use move_core_types::parsing::types::ParsedModuleId;
194 ParsedModuleId::parse(s)?.into_module_id(&resolve_address)
195}
196
197pub fn parse_sui_fq_name(s: &str) -> anyhow::Result<(ModuleId, String)> {
202 use move_core_types::parsing::types::ParsedFqName;
203 ParsedFqName::parse(s)?.into_fq_name(&resolve_address)
204}
205
206pub fn parse_sui_struct_tag(s: &str) -> anyhow::Result<StructTag> {
211 use move_core_types::parsing::types::ParsedDatatype;
212 ParsedDatatype::parse(s)?.into_struct_tag(&resolve_address)
213}
214
215pub fn parse_sui_type_tag(s: &str) -> anyhow::Result<TypeTag> {
219 use move_core_types::parsing::types::ParsedType;
220 ParsedType::parse(s)?.into_type_tag(&resolve_address)
221}
222
223pub fn resolve_address(addr: &str) -> Option<AccountAddress> {
225 match addr {
226 "deepbook" => Some(DEEPBOOK_ADDRESS),
227 "std" => Some(MOVE_STDLIB_ADDRESS),
228 "sui" => Some(SUI_FRAMEWORK_ADDRESS),
229 "sui_system" => Some(SUI_SYSTEM_ADDRESS),
230 "bridge" => Some(BRIDGE_ADDRESS),
231 _ => None,
232 }
233}
234
235pub trait MoveTypeTagTrait {
236 fn get_type_tag() -> TypeTag;
237
238 fn get_instance_type_tag(&self) -> TypeTag {
239 Self::get_type_tag()
240 }
241}
242
243impl MoveTypeTagTrait for u8 {
244 fn get_type_tag() -> TypeTag {
245 TypeTag::U8
246 }
247}
248
249impl MoveTypeTagTrait for u64 {
250 fn get_type_tag() -> TypeTag {
251 TypeTag::U64
252 }
253}
254
255impl MoveTypeTagTrait for ObjectID {
256 fn get_type_tag() -> TypeTag {
257 TypeTag::Address
258 }
259}
260
261impl MoveTypeTagTrait for SuiAddress {
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 trait MoveTypeTagTraitGeneric {
274 fn get_type_tag(type_params: &[TypeTag]) -> TypeTag;
275}
276
277pub fn is_primitive(
278 view: &CompiledModule,
279 function_type_args: &[AbilitySet],
280 s: &SignatureToken,
281) -> bool {
282 use SignatureToken as S;
283 match s {
284 S::Bool | S::U8 | S::U16 | S::U32 | S::U64 | S::U128 | S::U256 | S::Address => true,
285 S::Signer => false,
286 S::TypeParameter(idx) => !function_type_args[*idx as usize].has_key(),
288
289 S::Datatype(idx) => [RESOLVED_SUI_ID, RESOLVED_ASCII_STR, RESOLVED_UTF8_STR]
290 .contains(&resolve_struct(view, *idx)),
291
292 S::DatatypeInstantiation(inst) => {
293 let (idx, targs) = &**inst;
294 let resolved_struct = resolve_struct(view, *idx);
295 resolved_struct == RESOLVED_STD_OPTION
297 && targs.len() == 1
298 && is_primitive(view, function_type_args, &targs[0])
299 }
300
301 S::Vector(inner) => is_primitive(view, function_type_args, inner),
302 S::Reference(_) | S::MutableReference(_) => false,
303 }
304}
305
306pub fn is_object(
307 view: &CompiledModule,
308 function_type_args: &[AbilitySet],
309 t: &SignatureToken,
310) -> Result<bool, String> {
311 use SignatureToken as S;
312 match t {
313 S::Reference(inner) | S::MutableReference(inner) => {
314 is_object(view, function_type_args, inner)
315 }
316 _ => is_object_struct(view, function_type_args, t),
317 }
318}
319
320pub fn is_object_vector(
321 view: &CompiledModule,
322 function_type_args: &[AbilitySet],
323 t: &SignatureToken,
324) -> Result<bool, String> {
325 use SignatureToken as S;
326 match t {
327 S::Vector(inner) => is_object_struct(view, function_type_args, inner),
328 _ => is_object_struct(view, function_type_args, t),
329 }
330}
331
332fn is_object_struct(
333 view: &CompiledModule,
334 function_type_args: &[AbilitySet],
335 s: &SignatureToken,
336) -> Result<bool, String> {
337 use SignatureToken as S;
338 match s {
339 S::Bool
340 | S::U8
341 | S::U16
342 | S::U32
343 | S::U64
344 | S::U128
345 | S::U256
346 | S::Address
347 | S::Signer
348 | S::Vector(_)
349 | S::Reference(_)
350 | S::MutableReference(_) => Ok(false),
351 S::TypeParameter(idx) => Ok(function_type_args
352 .get(*idx as usize)
353 .map(|abs| abs.has_key())
354 .unwrap_or(false)),
355 S::Datatype(_) | S::DatatypeInstantiation(_) => {
356 let abilities = view
357 .abilities(s, function_type_args)
358 .map_err(|vm_err| vm_err.to_string())?;
359 Ok(abilities.has_key())
360 }
361 }
362}
363
364#[cfg(test)]
365mod tests {
366 use super::*;
367 use expect_test::expect;
368
369 #[test]
370 fn test_parse_sui_numeric_address() {
371 let result = parse_sui_address("0x2").expect("should not error");
372
373 let expected =
374 expect!["0x0000000000000000000000000000000000000000000000000000000000000002"];
375 expected.assert_eq(&result.to_string());
376 }
377
378 #[test]
379 fn test_parse_sui_named_address() {
380 let result = parse_sui_address("sui").expect("should not error");
381
382 let expected =
383 expect!["0x0000000000000000000000000000000000000000000000000000000000000002"];
384 expected.assert_eq(&result.to_string());
385 }
386
387 #[test]
388 fn test_parse_sui_module_id() {
389 let result = parse_sui_module_id("0x2::sui").expect("should not error");
390 let expected =
391 expect!["0x0000000000000000000000000000000000000000000000000000000000000002::sui"];
392 expected.assert_eq(&result.to_canonical_string(true));
393 }
394
395 #[test]
396 fn test_parse_sui_fq_name() {
397 let (module, name) = parse_sui_fq_name("0x2::object::new").expect("should not error");
398 let expected = expect![
399 "0x0000000000000000000000000000000000000000000000000000000000000002::object::new"
400 ];
401 expected.assert_eq(&format!(
402 "{}::{name}",
403 module.to_canonical_display(true)
404 ));
405 }
406
407 #[test]
408 fn test_parse_sui_struct_tag_short_account_addr() {
409 let result = parse_sui_struct_tag("0x2::sui::SUI").expect("should not error");
410
411 let expected = expect!["0x2::sui::SUI"];
412 expected.assert_eq(&result.to_string());
413
414 let expected =
415 expect!["0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI"];
416 expected.assert_eq(&result.to_canonical_string(true));
417 }
418
419 #[test]
420 fn test_parse_sui_struct_tag_long_account_addr() {
421 let result = parse_sui_struct_tag(
422 "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI",
423 )
424 .expect("should not error");
425
426 let expected = expect!["0x2::sui::SUI"];
427 expected.assert_eq(&result.to_string());
428
429 let expected =
430 expect!["0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI"];
431 expected.assert_eq(&result.to_canonical_string(true));
432 }
433
434 #[test]
435 fn test_parse_sui_struct_with_type_param_short_addr() {
436 let result =
437 parse_sui_struct_tag("0x2::coin::COIN<0x2::sui::SUI>").expect("should not error");
438
439 let expected = expect!["0x2::coin::COIN<0x2::sui::SUI>"];
440 expected.assert_eq(&result.to_string());
441
442 let expected = expect![
443 "0x0000000000000000000000000000000000000000000000000000000000000002::coin::COIN<0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI>"
444 ];
445 expected.assert_eq(&result.to_canonical_string(true));
446 }
447
448 #[test]
449 fn test_parse_sui_struct_with_type_param_long_addr() {
450 let result = parse_sui_struct_tag("0x0000000000000000000000000000000000000000000000000000000000000002::coin::COIN<0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI>")
451 .expect("should not error");
452
453 let expected = expect!["0x2::coin::COIN<0x2::sui::SUI>"];
454 expected.assert_eq(&result.to_string());
455
456 let expected = expect![
457 "0x0000000000000000000000000000000000000000000000000000000000000002::coin::COIN<0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI>"
458 ];
459 expected.assert_eq(&result.to_canonical_string(true));
460 }
461
462 #[test]
463 fn test_complex_struct_tag_with_short_addr() {
464 let result =
465 parse_sui_struct_tag("0xe7::vec_coin::VecCoin<vector<0x2::coin::Coin<0x2::sui::SUI>>>")
466 .expect("should not error");
467
468 let expected = expect!["0xe7::vec_coin::VecCoin<vector<0x2::coin::Coin<0x2::sui::SUI>>>"];
469 expected.assert_eq(&result.to_string());
470
471 let expected = expect![
472 "0x00000000000000000000000000000000000000000000000000000000000000e7::vec_coin::VecCoin<vector<0x0000000000000000000000000000000000000000000000000000000000000002::coin::Coin<0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI>>>"
473 ];
474 expected.assert_eq(&result.to_canonical_string(true));
475 }
476
477 #[test]
478 fn test_complex_struct_tag_with_long_addr() {
479 let result = parse_sui_struct_tag("0x00000000000000000000000000000000000000000000000000000000000000e7::vec_coin::VecCoin<vector<0x0000000000000000000000000000000000000000000000000000000000000002::coin::Coin<0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI>>>")
480 .expect("should not error");
481
482 let expected = expect!["0xe7::vec_coin::VecCoin<vector<0x2::coin::Coin<0x2::sui::SUI>>>"];
483 expected.assert_eq(&result.to_string());
484
485 let expected = expect![
486 "0x00000000000000000000000000000000000000000000000000000000000000e7::vec_coin::VecCoin<vector<0x0000000000000000000000000000000000000000000000000000000000000002::coin::Coin<0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI>>>"
487 ];
488 expected.assert_eq(&result.to_canonical_string(true));
489 }
490
491 #[test]
492 fn test_dynamic_field_short_addr() {
493 let result = parse_sui_struct_tag(
494 "0x2::dynamic_field::Field<address, 0xdee9::custodian_v2::Account<0x234::coin::COIN>>",
495 )
496 .expect("should not error");
497
498 let expected = expect![
499 "0x2::dynamic_field::Field<address, 0xdee9::custodian_v2::Account<0x234::coin::COIN>>"
500 ];
501 expected.assert_eq(&result.to_string());
502
503 let expected = expect![
504 "0x0000000000000000000000000000000000000000000000000000000000000002::dynamic_field::Field<address,0x000000000000000000000000000000000000000000000000000000000000dee9::custodian_v2::Account<0x0000000000000000000000000000000000000000000000000000000000000234::coin::COIN>>"
505 ];
506 expected.assert_eq(&result.to_canonical_string(true));
507 }
508
509 #[test]
510 fn test_dynamic_field_long_addr() {
511 let result = parse_sui_struct_tag(
512 "0x2::dynamic_field::Field<address, 0xdee9::custodian_v2::Account<0x234::coin::COIN>>",
513 )
514 .expect("should not error");
515
516 let expected = expect![
517 "0x2::dynamic_field::Field<address, 0xdee9::custodian_v2::Account<0x234::coin::COIN>>"
518 ];
519 expected.assert_eq(&result.to_string());
520
521 let expected = expect![
522 "0x0000000000000000000000000000000000000000000000000000000000000002::dynamic_field::Field<address,0x000000000000000000000000000000000000000000000000000000000000dee9::custodian_v2::Account<0x0000000000000000000000000000000000000000000000000000000000000234::coin::COIN>>"
523 ];
524 expected.assert_eq(&result.to_canonical_string(true));
525 }
526}