radix_transactions/manifest/
manifest_instructions.rs

1use crate::internal_prelude::*;
2use decompiler::*;
3use radix_engine_interface::blueprints::access_controller::*;
4use radix_engine_interface::blueprints::account::*;
5use radix_engine_interface::blueprints::consensus_manager::*;
6use radix_engine_interface::blueprints::identity::*;
7use radix_engine_interface::blueprints::package::*;
8use radix_engine_interface::blueprints::resource::*;
9use radix_engine_interface::object_modules::metadata::*;
10use radix_engine_interface::object_modules::role_assignment::*;
11use radix_engine_interface::object_modules::royalty::*;
12
13use ManifestInstructionEffect as Effect;
14
15pub trait ManifestInstruction: Into<AnyInstruction> {
16    const IDENT: &'static str;
17    const ID: u8;
18
19    fn decompile(
20        &self,
21        context: &mut DecompilationContext,
22    ) -> Result<DecompiledInstruction, DecompileError>;
23
24    fn effect(&self) -> Effect;
25
26    fn into_any(self) -> AnyInstruction {
27        self.into()
28    }
29}
30
31//======================================================================
32// region:Bucket Lifecycle
33//======================================================================
34
35/// Takes a bucket containing the given amount of resource from the worktop,
36/// and binds the given bucket name to that bucket.
37#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
38pub struct TakeFromWorktop {
39    pub resource_address: ResourceAddress,
40    pub amount: Decimal,
41}
42
43impl ManifestInstruction for TakeFromWorktop {
44    const IDENT: &'static str = "TAKE_FROM_WORKTOP";
45    const ID: u8 = INSTRUCTION_TAKE_FROM_WORKTOP_DISCRIMINATOR;
46
47    fn decompile(
48        &self,
49        context: &mut DecompilationContext,
50    ) -> Result<DecompiledInstruction, DecompileError> {
51        let instruction = DecompiledInstruction::new(Self::IDENT)
52            .add_argument(&self.resource_address)
53            .add_argument(&self.amount)
54            .add_argument(context.new_bucket());
55        Ok(instruction)
56    }
57
58    fn effect(&self) -> Effect {
59        Effect::CreateBucket {
60            source_amount: BucketSourceAmount::AmountFromWorktop {
61                resource_address: &self.resource_address,
62                amount: self.amount,
63            },
64        }
65    }
66}
67
68/// Takes a bucket containing the given non-fungible ids of the resource from the worktop,
69/// and binds the given bucket name to that bucket.
70#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
71pub struct TakeNonFungiblesFromWorktop {
72    pub resource_address: ResourceAddress,
73    pub ids: Vec<NonFungibleLocalId>,
74}
75
76impl ManifestInstruction for TakeNonFungiblesFromWorktop {
77    const IDENT: &'static str = "TAKE_NON_FUNGIBLES_FROM_WORKTOP";
78    const ID: u8 = INSTRUCTION_TAKE_NON_FUNGIBLES_FROM_WORKTOP_DISCRIMINATOR;
79
80    fn decompile(
81        &self,
82        context: &mut DecompilationContext,
83    ) -> Result<DecompiledInstruction, DecompileError> {
84        let instruction = DecompiledInstruction::new(Self::IDENT)
85            .add_argument(&self.resource_address)
86            .add_argument(&self.ids)
87            .add_argument(context.new_bucket());
88        Ok(instruction)
89    }
90
91    fn effect(&self) -> Effect {
92        Effect::CreateBucket {
93            source_amount: BucketSourceAmount::NonFungiblesFromWorktop {
94                resource_address: &self.resource_address,
95                ids: &self.ids,
96            },
97        }
98    }
99}
100
101/// Takes a bucket containing all of a given resource from the worktop,
102/// and binds the given bucket name to that bucket.
103#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
104pub struct TakeAllFromWorktop {
105    pub resource_address: ResourceAddress,
106}
107
108impl ManifestInstruction for TakeAllFromWorktop {
109    const IDENT: &'static str = "TAKE_ALL_FROM_WORKTOP";
110    const ID: u8 = INSTRUCTION_TAKE_ALL_FROM_WORKTOP_DISCRIMINATOR;
111
112    fn decompile(
113        &self,
114        context: &mut DecompilationContext,
115    ) -> Result<DecompiledInstruction, DecompileError> {
116        let instruction = DecompiledInstruction::new(Self::IDENT)
117            .add_argument(&self.resource_address)
118            .add_argument(context.new_bucket());
119        Ok(instruction)
120    }
121
122    fn effect(&self) -> Effect {
123        Effect::CreateBucket {
124            source_amount: BucketSourceAmount::AllOnWorktop {
125                resource_address: &self.resource_address,
126            },
127        }
128    }
129}
130
131/// Returns a bucket to the worktop.
132#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
133pub struct ReturnToWorktop {
134    pub bucket_id: ManifestBucket,
135}
136
137impl ManifestInstruction for ReturnToWorktop {
138    const IDENT: &'static str = "RETURN_TO_WORKTOP";
139    const ID: u8 = INSTRUCTION_RETURN_TO_WORKTOP_DISCRIMINATOR;
140
141    fn decompile(
142        &self,
143        _context: &mut DecompilationContext,
144    ) -> Result<DecompiledInstruction, DecompileError> {
145        let instruction = DecompiledInstruction::new(Self::IDENT).add_argument(&self.bucket_id);
146        Ok(instruction)
147    }
148
149    fn effect(&self) -> Effect {
150        Effect::ConsumeBucket {
151            consumed_bucket: self.bucket_id,
152            destination: BucketDestination::Worktop,
153        }
154    }
155}
156
157/// Burns the bucket.
158#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
159pub struct BurnResource {
160    pub bucket_id: ManifestBucket,
161}
162
163impl ManifestInstruction for BurnResource {
164    const IDENT: &'static str = "BURN_RESOURCE";
165    const ID: u8 = INSTRUCTION_BURN_RESOURCE_DISCRIMINATOR;
166
167    fn decompile(
168        &self,
169        _context: &mut DecompilationContext,
170    ) -> Result<DecompiledInstruction, DecompileError> {
171        let instruction = DecompiledInstruction::new(Self::IDENT).add_argument(&self.bucket_id);
172        Ok(instruction)
173    }
174
175    fn effect(&self) -> Effect {
176        Effect::ConsumeBucket {
177            consumed_bucket: self.bucket_id,
178            destination: BucketDestination::Burned,
179        }
180    }
181}
182
183//======================================================================
184// region:Resource Assertions
185//======================================================================
186
187/// Asserts that the worktop contains any positive amount of the specified resource.
188#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
189pub struct AssertWorktopContainsAny {
190    pub resource_address: ResourceAddress,
191}
192
193impl ManifestInstruction for AssertWorktopContainsAny {
194    const IDENT: &'static str = "ASSERT_WORKTOP_CONTAINS_ANY";
195    const ID: u8 = INSTRUCTION_ASSERT_WORKTOP_CONTAINS_ANY_DISCRIMINATOR;
196
197    fn decompile(
198        &self,
199        _context: &mut DecompilationContext,
200    ) -> Result<DecompiledInstruction, DecompileError> {
201        let instruction =
202            DecompiledInstruction::new(Self::IDENT).add_argument(&self.resource_address);
203        Ok(instruction)
204    }
205
206    fn effect(&self) -> Effect {
207        Effect::ResourceAssertion {
208            assertion: ResourceAssertion::Worktop(WorktopAssertion::ResourceNonZeroAmount {
209                resource_address: &self.resource_address,
210            }),
211        }
212    }
213}
214
215/// Asserts that the worktop contains at least the given amount of the specified resource.
216#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
217pub struct AssertWorktopContains {
218    pub resource_address: ResourceAddress,
219    pub amount: Decimal,
220}
221
222impl ManifestInstruction for AssertWorktopContains {
223    const IDENT: &'static str = "ASSERT_WORKTOP_CONTAINS";
224    const ID: u8 = INSTRUCTION_ASSERT_WORKTOP_CONTAINS_DISCRIMINATOR;
225
226    fn decompile(
227        &self,
228        _context: &mut DecompilationContext,
229    ) -> Result<DecompiledInstruction, DecompileError> {
230        let instruction = DecompiledInstruction::new(Self::IDENT)
231            .add_argument(&self.resource_address)
232            .add_argument(&self.amount);
233        Ok(instruction)
234    }
235
236    fn effect(&self) -> Effect {
237        Effect::ResourceAssertion {
238            assertion: ResourceAssertion::Worktop(WorktopAssertion::ResourceAtLeastAmount {
239                resource_address: &self.resource_address,
240                amount: self.amount,
241            }),
242        }
243    }
244}
245
246/// Asserts that the worktop contains at least the given non-fungible ids of the specified resource.
247#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
248pub struct AssertWorktopContainsNonFungibles {
249    pub resource_address: ResourceAddress,
250    pub ids: Vec<NonFungibleLocalId>,
251}
252
253impl ManifestInstruction for AssertWorktopContainsNonFungibles {
254    const IDENT: &'static str = "ASSERT_WORKTOP_CONTAINS_NON_FUNGIBLES";
255    const ID: u8 = INSTRUCTION_ASSERT_WORKTOP_CONTAINS_NON_FUNGIBLES_DISCRIMINATOR;
256
257    fn decompile(
258        &self,
259        _context: &mut DecompilationContext,
260    ) -> Result<DecompiledInstruction, DecompileError> {
261        let instruction = DecompiledInstruction::new(Self::IDENT)
262            .add_argument(&self.resource_address)
263            .add_argument(&self.ids);
264        Ok(instruction)
265    }
266
267    fn effect(&self) -> Effect {
268        Effect::ResourceAssertion {
269            assertion: ResourceAssertion::Worktop(WorktopAssertion::ResourceAtLeastNonFungibles {
270                resource_address: &self.resource_address,
271                ids: &self.ids,
272            }),
273        }
274    }
275}
276
277/// Asserts that the worktop contains only these specified resources.
278///
279/// Each of the specified resources must satisfy the given constraints.
280#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
281pub struct AssertWorktopResourcesOnly {
282    pub constraints: ManifestResourceConstraints,
283}
284
285impl ManifestInstruction for AssertWorktopResourcesOnly {
286    const IDENT: &'static str = "ASSERT_WORKTOP_RESOURCES_ONLY";
287    const ID: u8 = INSTRUCTION_ASSERT_WORKTOP_RESOURCES_ONLY_DISCRIMINATOR;
288
289    fn decompile(
290        &self,
291        _context: &mut DecompilationContext,
292    ) -> Result<DecompiledInstruction, DecompileError> {
293        let instruction = if self.constraints.specified_resources().len() == 0 {
294            DecompiledInstruction::new("ASSERT_WORKTOP_IS_EMPTY")
295        } else {
296            DecompiledInstruction::new(Self::IDENT).add_argument(&self.constraints)
297        };
298
299        Ok(instruction)
300    }
301
302    fn effect(&self) -> Effect {
303        Effect::ResourceAssertion {
304            assertion: ResourceAssertion::Worktop(WorktopAssertion::ResourcesOnly {
305                constraints: &self.constraints,
306            }),
307        }
308    }
309}
310
311/// Asserts that the worktop includes these specified resources, and may
312/// also include other unspecified resources.
313///
314/// Each of the specified resources must satisfy the given constraints.
315#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
316pub struct AssertWorktopResourcesInclude {
317    pub constraints: ManifestResourceConstraints,
318}
319
320impl ManifestInstruction for AssertWorktopResourcesInclude {
321    const IDENT: &'static str = "ASSERT_WORKTOP_RESOURCES_INCLUDE";
322    const ID: u8 = INSTRUCTION_ASSERT_WORKTOP_RESOURCES_INCLUDE_DISCRIMINATOR;
323
324    fn decompile(
325        &self,
326        _context: &mut DecompilationContext,
327    ) -> Result<DecompiledInstruction, DecompileError> {
328        let instruction = DecompiledInstruction::new(Self::IDENT).add_argument(&self.constraints);
329        Ok(instruction)
330    }
331
332    fn effect(&self) -> Effect {
333        Effect::ResourceAssertion {
334            assertion: ResourceAssertion::Worktop(WorktopAssertion::ResourcesInclude {
335                constraints: &self.constraints,
336            }),
337        }
338    }
339}
340
341/// Asserts that the next invocation (`CALL` / `YIELD`) in the manifest
342/// returns only these specified resources.
343///
344/// Each of the specified resources must satisfy the given constraints.
345///
346/// Only one `ASSERT_NEXT_CALL_RETURNS_...` instruction may be specified
347/// per `CALL` / `YIELD`, and it must immediately precede it.
348#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
349pub struct AssertNextCallReturnsOnly {
350    pub constraints: ManifestResourceConstraints,
351}
352
353impl ManifestInstruction for AssertNextCallReturnsOnly {
354    const IDENT: &'static str = "ASSERT_NEXT_CALL_RETURNS_ONLY";
355    const ID: u8 = INSTRUCTION_ASSERT_NEXT_CALL_RETURNS_ONLY_DISCRIMINATOR;
356
357    fn decompile(
358        &self,
359        _context: &mut DecompilationContext,
360    ) -> Result<DecompiledInstruction, DecompileError> {
361        let instruction = DecompiledInstruction::new(Self::IDENT).add_argument(&self.constraints);
362        Ok(instruction)
363    }
364
365    fn effect(&self) -> Effect {
366        Effect::ResourceAssertion {
367            assertion: ResourceAssertion::NextCall(NextCallAssertion::ReturnsOnly {
368                constraints: &self.constraints,
369            }),
370        }
371    }
372}
373
374/// Asserts that the next invocation (`CALL` / `YIELD`) in the manifest
375/// returns these specified resources, and may also include other
376/// unspecified resources.
377///
378/// Each of the specified resources must satisfy the given constraints.
379///
380/// Only one `ASSERT_NEXT_CALL_RETURNS_...` instruction may be specified
381/// per `CALL` / `YIELD`, and it must immediately precede it.
382#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
383pub struct AssertNextCallReturnsInclude {
384    pub constraints: ManifestResourceConstraints,
385}
386
387impl ManifestInstruction for AssertNextCallReturnsInclude {
388    const IDENT: &'static str = "ASSERT_NEXT_CALL_RETURNS_INCLUDE";
389    const ID: u8 = INSTRUCTION_ASSERT_NEXT_CALL_RETURNS_INCLUDE_DISCRIMINATOR;
390
391    fn decompile(
392        &self,
393        _context: &mut DecompilationContext,
394    ) -> Result<DecompiledInstruction, DecompileError> {
395        let instruction = DecompiledInstruction::new(Self::IDENT).add_argument(&self.constraints);
396        Ok(instruction)
397    }
398
399    fn effect(&self) -> Effect {
400        Effect::ResourceAssertion {
401            assertion: ResourceAssertion::NextCall(NextCallAssertion::ReturnsInclude {
402                constraints: &self.constraints,
403            }),
404        }
405    }
406}
407
408/// Asserts that the contents of the named bucket satisfy the given constraints.
409#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
410pub struct AssertBucketContents {
411    pub bucket_id: ManifestBucket,
412    pub constraint: ManifestResourceConstraint,
413}
414
415impl ManifestInstruction for AssertBucketContents {
416    const IDENT: &'static str = "ASSERT_BUCKET_CONTENTS";
417    const ID: u8 = INSTRUCTION_ASSERT_BUCKET_CONTENTS_DISCRIMINATOR;
418
419    fn decompile(
420        &self,
421        _context: &mut DecompilationContext,
422    ) -> Result<DecompiledInstruction, DecompileError> {
423        let instruction = DecompiledInstruction::new(Self::IDENT)
424            .add_argument(&self.bucket_id)
425            .add_argument(&self.constraint);
426        Ok(instruction)
427    }
428
429    fn effect(&self) -> Effect {
430        Effect::ResourceAssertion {
431            assertion: ResourceAssertion::Bucket(BucketAssertion::Contents {
432                bucket: self.bucket_id,
433                constraint: &self.constraint,
434            }),
435        }
436    }
437}
438
439//======================================================================
440// region:Proof Lifecycle
441//======================================================================
442
443/// Creates a proof of the specific amount of the given resource,
444/// backed by the contents of this bucket. The proof must be dropped
445/// before the bucket can be fully emptied.
446#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
447pub struct CreateProofFromBucketOfAmount {
448    pub bucket_id: ManifestBucket,
449    pub amount: Decimal,
450}
451
452impl ManifestInstruction for CreateProofFromBucketOfAmount {
453    const IDENT: &'static str = "CREATE_PROOF_FROM_BUCKET_OF_AMOUNT";
454    const ID: u8 = INSTRUCTION_CREATE_PROOF_FROM_BUCKET_OF_AMOUNT_DISCRIMINATOR;
455
456    fn decompile(
457        &self,
458        context: &mut DecompilationContext,
459    ) -> Result<DecompiledInstruction, DecompileError> {
460        let instruction = DecompiledInstruction::new(Self::IDENT)
461            .add_argument(&self.bucket_id)
462            .add_argument(&self.amount)
463            .add_argument(context.new_proof());
464        Ok(instruction)
465    }
466
467    fn effect(&self) -> Effect {
468        Effect::CreateProof {
469            source_amount: ProofSourceAmount::BucketAmount {
470                bucket: self.bucket_id,
471                amount: self.amount,
472            },
473        }
474    }
475}
476
477/// Creates a proof of the specific non-fungibles of the given resource,
478/// backed by the contents of this bucket. The proof must be dropped
479/// before the bucket can be fully emptied.
480#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
481pub struct CreateProofFromBucketOfNonFungibles {
482    pub bucket_id: ManifestBucket,
483    pub ids: Vec<NonFungibleLocalId>,
484}
485
486impl ManifestInstruction for CreateProofFromBucketOfNonFungibles {
487    const IDENT: &'static str = "CREATE_PROOF_FROM_BUCKET_OF_NON_FUNGIBLES";
488    const ID: u8 = INSTRUCTION_CREATE_PROOF_FROM_BUCKET_OF_NON_FUNGIBLES_DISCRIMINATOR;
489
490    fn decompile(
491        &self,
492        context: &mut DecompilationContext,
493    ) -> Result<DecompiledInstruction, DecompileError> {
494        let instruction = DecompiledInstruction::new(Self::IDENT)
495            .add_argument(&self.bucket_id)
496            .add_argument(&self.ids)
497            .add_argument(context.new_proof());
498        Ok(instruction)
499    }
500
501    fn effect(&self) -> Effect {
502        Effect::CreateProof {
503            source_amount: ProofSourceAmount::BucketNonFungibles {
504                bucket: self.bucket_id,
505                ids: &self.ids,
506            },
507        }
508    }
509}
510
511/// Creates a proof of the given resource, backed by the contents
512/// of this bucket. The proof must be dropped before the bucket can
513/// be fully emptied.
514#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
515pub struct CreateProofFromBucketOfAll {
516    pub bucket_id: ManifestBucket,
517}
518
519impl ManifestInstruction for CreateProofFromBucketOfAll {
520    const IDENT: &'static str = "CREATE_PROOF_FROM_BUCKET_OF_ALL";
521    const ID: u8 = INSTRUCTION_CREATE_PROOF_FROM_BUCKET_OF_ALL_DISCRIMINATOR;
522
523    fn decompile(
524        &self,
525        context: &mut DecompilationContext,
526    ) -> Result<DecompiledInstruction, DecompileError> {
527        let instruction = DecompiledInstruction::new(Self::IDENT)
528            .add_argument(&self.bucket_id)
529            .add_argument(context.new_proof());
530        Ok(instruction)
531    }
532
533    fn effect(&self) -> Effect {
534        Effect::CreateProof {
535            source_amount: ProofSourceAmount::BucketAllOf {
536                bucket: self.bucket_id,
537            },
538        }
539    }
540}
541
542/// Creates a proof of the given amount, by combining the backing from
543/// one or more proofs available in the auth zone.
544#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
545pub struct CreateProofFromAuthZoneOfAmount {
546    pub resource_address: ResourceAddress,
547    pub amount: Decimal,
548}
549
550impl ManifestInstruction for CreateProofFromAuthZoneOfAmount {
551    const IDENT: &'static str = "CREATE_PROOF_FROM_AUTH_ZONE_OF_AMOUNT";
552    const ID: u8 = INSTRUCTION_CREATE_PROOF_FROM_AUTH_ZONE_OF_AMOUNT_DISCRIMINATOR;
553
554    fn decompile(
555        &self,
556        context: &mut DecompilationContext,
557    ) -> Result<DecompiledInstruction, DecompileError> {
558        let instruction = DecompiledInstruction::new(Self::IDENT)
559            .add_argument(&self.resource_address)
560            .add_argument(&self.amount)
561            .add_argument(context.new_proof());
562        Ok(instruction)
563    }
564
565    fn effect(&self) -> Effect {
566        Effect::CreateProof {
567            source_amount: ProofSourceAmount::AuthZoneAmount {
568                resource_address: &self.resource_address,
569                amount: self.amount,
570            },
571        }
572    }
573}
574
575/// Creates a proof of the given non-fungible ids, by combining the backing from
576/// one or more proofs available in the auth zone.
577#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
578pub struct CreateProofFromAuthZoneOfNonFungibles {
579    pub resource_address: ResourceAddress,
580    pub ids: Vec<NonFungibleLocalId>,
581}
582
583impl ManifestInstruction for CreateProofFromAuthZoneOfNonFungibles {
584    const IDENT: &'static str = "CREATE_PROOF_FROM_AUTH_ZONE_OF_NON_FUNGIBLES";
585    const ID: u8 = INSTRUCTION_CREATE_PROOF_FROM_AUTH_ZONE_OF_NON_FUNGIBLES_DISCRIMINATOR;
586
587    fn decompile(
588        &self,
589        context: &mut DecompilationContext,
590    ) -> Result<DecompiledInstruction, DecompileError> {
591        let instruction = DecompiledInstruction::new(Self::IDENT)
592            .add_argument(&self.resource_address)
593            .add_argument(&self.ids)
594            .add_argument(context.new_proof());
595        Ok(instruction)
596    }
597
598    fn effect(&self) -> Effect {
599        Effect::CreateProof {
600            source_amount: ProofSourceAmount::AuthZoneNonFungibles {
601                resource_address: &self.resource_address,
602                ids: &self.ids,
603            },
604        }
605    }
606}
607
608/// Creates a proof of the given resource, by combining the backing from
609/// all of the proofs for that resource in the auth zone.
610#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
611pub struct CreateProofFromAuthZoneOfAll {
612    pub resource_address: ResourceAddress,
613}
614
615impl ManifestInstruction for CreateProofFromAuthZoneOfAll {
616    const IDENT: &'static str = "CREATE_PROOF_FROM_AUTH_ZONE_OF_ALL";
617    const ID: u8 = INSTRUCTION_CREATE_PROOF_FROM_AUTH_ZONE_OF_ALL_DISCRIMINATOR;
618
619    fn decompile(
620        &self,
621        context: &mut DecompilationContext,
622    ) -> Result<DecompiledInstruction, DecompileError> {
623        let instruction = DecompiledInstruction::new(Self::IDENT)
624            .add_argument(&self.resource_address)
625            .add_argument(context.new_proof());
626        Ok(instruction)
627    }
628
629    fn effect(&self) -> Effect {
630        Effect::CreateProof {
631            source_amount: ProofSourceAmount::AuthZoneAllOf {
632                resource_address: &self.resource_address,
633            },
634        }
635    }
636}
637
638/// Clones a named proof (first argument), creating a new named proof (second argument).
639#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
640pub struct CloneProof {
641    pub proof_id: ManifestProof,
642}
643
644impl ManifestInstruction for CloneProof {
645    const IDENT: &'static str = "CLONE_PROOF";
646    const ID: u8 = INSTRUCTION_CLONE_PROOF_DISCRIMINATOR;
647
648    fn decompile(
649        &self,
650        context: &mut DecompilationContext,
651    ) -> Result<DecompiledInstruction, DecompileError> {
652        let instruction = DecompiledInstruction::new(Self::IDENT)
653            .add_argument(&self.proof_id)
654            .add_argument(context.new_proof());
655        Ok(instruction)
656    }
657
658    fn effect(&self) -> Effect {
659        Effect::CloneProof {
660            cloned_proof: self.proof_id,
661        }
662    }
663}
664
665/// Drops a named proof.
666#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
667pub struct DropProof {
668    pub proof_id: ManifestProof,
669}
670
671impl ManifestInstruction for DropProof {
672    const IDENT: &'static str = "DROP_PROOF";
673    const ID: u8 = INSTRUCTION_DROP_PROOF_DISCRIMINATOR;
674
675    fn decompile(
676        &self,
677        _context: &mut DecompilationContext,
678    ) -> Result<DecompiledInstruction, DecompileError> {
679        let instruction = DecompiledInstruction::new(Self::IDENT).add_argument(&self.proof_id);
680        Ok(instruction)
681    }
682
683    fn effect(&self) -> Effect {
684        Effect::ConsumeProof {
685            consumed_proof: self.proof_id,
686            destination: ProofDestination::Drop,
687        }
688    }
689}
690
691/// Puts a named proof into the auth zone.
692#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
693pub struct PushToAuthZone {
694    pub proof_id: ManifestProof,
695}
696
697impl ManifestInstruction for PushToAuthZone {
698    const IDENT: &'static str = "PUSH_TO_AUTH_ZONE";
699    const ID: u8 = INSTRUCTION_PUSH_TO_AUTH_ZONE_DISCRIMINATOR;
700
701    fn decompile(
702        &self,
703        _context: &mut DecompilationContext,
704    ) -> Result<DecompiledInstruction, DecompileError> {
705        let instruction = DecompiledInstruction::new(Self::IDENT).add_argument(&self.proof_id);
706        Ok(instruction)
707    }
708
709    fn effect(&self) -> Effect {
710        Effect::ConsumeProof {
711            consumed_proof: self.proof_id,
712            destination: ProofDestination::AuthZone,
713        }
714    }
715}
716
717/// Takes the last proof from the auth zone, and makes it a named proof.
718#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
719pub struct PopFromAuthZone;
720
721impl ManifestInstruction for PopFromAuthZone {
722    const IDENT: &'static str = "POP_FROM_AUTH_ZONE";
723    const ID: u8 = INSTRUCTION_POP_FROM_AUTH_ZONE_DISCRIMINATOR;
724
725    fn decompile(
726        &self,
727        context: &mut DecompilationContext,
728    ) -> Result<DecompiledInstruction, DecompileError> {
729        let instruction = DecompiledInstruction::new(Self::IDENT).add_argument(context.new_proof());
730        Ok(instruction)
731    }
732
733    fn effect(&self) -> Effect {
734        Effect::CreateProof {
735            source_amount: ProofSourceAmount::AuthZonePopLastAddedProof,
736        }
737    }
738}
739
740/// Drops all the proofs in the auth zone, potentially freeing up the assets locked in any containers backing the proofs.
741///
742/// Named proofs owned by the transaction processor are NOT dropped.
743#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
744pub struct DropAuthZoneProofs;
745
746impl ManifestInstruction for DropAuthZoneProofs {
747    const IDENT: &'static str = "DROP_AUTH_ZONE_PROOFS";
748    const ID: u8 = INSTRUCTION_DROP_AUTH_ZONE_PROOFS_DISCRIMINATOR;
749
750    fn decompile(
751        &self,
752        _context: &mut DecompilationContext,
753    ) -> Result<DecompiledInstruction, DecompileError> {
754        let instruction = DecompiledInstruction::new(Self::IDENT);
755        Ok(instruction)
756    }
757
758    fn effect(&self) -> Effect {
759        Effect::DropManyProofs {
760            drop_all_named_proofs: false,
761            drop_all_authzone_signature_proofs: true,
762            drop_all_authzone_non_signature_proofs: true,
763        }
764    }
765}
766
767/// Drops all the non-signature proofs in the auth zone, potentially freeing up the assets locked in any containers backing the proofs.
768///
769/// Signature proofs on the auth zone are NOT dropped. Named proofs owned by the transaction processor are also NOT dropped.
770#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
771pub struct DropAuthZoneRegularProofs;
772
773impl ManifestInstruction for DropAuthZoneRegularProofs {
774    const IDENT: &'static str = "DROP_AUTH_ZONE_REGULAR_PROOFS";
775    const ID: u8 = INSTRUCTION_DROP_AUTH_ZONE_REGULAR_PROOFS_DISCRIMINATOR;
776
777    fn decompile(
778        &self,
779        _context: &mut DecompilationContext,
780    ) -> Result<DecompiledInstruction, DecompileError> {
781        let instruction = DecompiledInstruction::new(Self::IDENT);
782        Ok(instruction)
783    }
784
785    fn effect(&self) -> Effect {
786        Effect::DropManyProofs {
787            drop_all_named_proofs: false,
788            drop_all_authzone_signature_proofs: false,
789            drop_all_authzone_non_signature_proofs: true,
790        }
791    }
792}
793
794/// Drops all the signature proofs in the auth zone, preventing any further calls from making use of signature-based authentication.
795///
796/// Regular proofs on the auth zone are NOT dropped, and named proofs owned by the transaction processor are also NOT dropped.
797#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
798pub struct DropAuthZoneSignatureProofs;
799
800impl ManifestInstruction for DropAuthZoneSignatureProofs {
801    const IDENT: &'static str = "DROP_AUTH_ZONE_SIGNATURE_PROOFS";
802    const ID: u8 = INSTRUCTION_DROP_AUTH_ZONE_SIGNATURE_PROOFS_DISCRIMINATOR;
803
804    fn decompile(
805        &self,
806        _context: &mut DecompilationContext,
807    ) -> Result<DecompiledInstruction, DecompileError> {
808        let instruction = DecompiledInstruction::new(Self::IDENT);
809        Ok(instruction)
810    }
811
812    fn effect(&self) -> Effect {
813        Effect::DropManyProofs {
814            drop_all_named_proofs: false,
815            drop_all_authzone_signature_proofs: true,
816            drop_all_authzone_non_signature_proofs: false,
817        }
818    }
819}
820
821/// Drops all named proofs owned by the transaction processor.
822///
823/// The proofs on the auth zone are NOT dropped.
824#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
825pub struct DropNamedProofs;
826
827impl ManifestInstruction for DropNamedProofs {
828    const IDENT: &'static str = "DROP_NAMED_PROOFS";
829    const ID: u8 = INSTRUCTION_DROP_NAMED_PROOFS_DISCRIMINATOR;
830
831    fn decompile(
832        &self,
833        _context: &mut DecompilationContext,
834    ) -> Result<DecompiledInstruction, DecompileError> {
835        let instruction = DecompiledInstruction::new(Self::IDENT);
836        Ok(instruction)
837    }
838
839    fn effect(&self) -> Effect {
840        Effect::DropManyProofs {
841            drop_all_named_proofs: true,
842            drop_all_authzone_signature_proofs: false,
843            drop_all_authzone_non_signature_proofs: false,
844        }
845    }
846}
847
848/// Drops all proofs, both named proofs and auth zone proofs.
849#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
850pub struct DropAllProofs;
851
852impl ManifestInstruction for DropAllProofs {
853    const IDENT: &'static str = "DROP_ALL_PROOFS";
854    const ID: u8 = INSTRUCTION_DROP_ALL_PROOFS_DISCRIMINATOR;
855
856    fn decompile(
857        &self,
858        _context: &mut DecompilationContext,
859    ) -> Result<DecompiledInstruction, DecompileError> {
860        let instruction = DecompiledInstruction::new(Self::IDENT);
861        Ok(instruction)
862    }
863
864    fn effect(&self) -> Effect {
865        Effect::DropManyProofs {
866            drop_all_named_proofs: true,
867            drop_all_authzone_signature_proofs: true,
868            drop_all_authzone_non_signature_proofs: true,
869        }
870    }
871}
872
873//======================================================================
874// region:Invocations
875//======================================================================
876
877#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
878pub struct CallFunction {
879    pub package_address: ManifestPackageAddress,
880    pub blueprint_name: String,
881    pub function_name: String,
882    pub args: ManifestValue,
883}
884
885impl CallFunction {
886    fn decompile_header(&self) -> DecompiledInstruction {
887        if let ManifestPackageAddress::Static(package_address) = &self.package_address {
888            match (
889                package_address,
890                self.blueprint_name.as_str(),
891                self.function_name.as_str(),
892            ) {
893                (&PACKAGE_PACKAGE, PACKAGE_BLUEPRINT, PACKAGE_PUBLISH_WASM_IDENT) => {
894                    return DecompiledInstruction::new("PUBLISH_PACKAGE");
895                }
896                (&PACKAGE_PACKAGE, PACKAGE_BLUEPRINT, PACKAGE_PUBLISH_WASM_ADVANCED_IDENT) => {
897                    return DecompiledInstruction::new("PUBLISH_PACKAGE_ADVANCED");
898                }
899                (&ACCOUNT_PACKAGE, ACCOUNT_BLUEPRINT, ACCOUNT_CREATE_ADVANCED_IDENT) => {
900                    return DecompiledInstruction::new("CREATE_ACCOUNT_ADVANCED");
901                }
902                (&ACCOUNT_PACKAGE, ACCOUNT_BLUEPRINT, ACCOUNT_CREATE_IDENT) => {
903                    return DecompiledInstruction::new("CREATE_ACCOUNT");
904                }
905                (&IDENTITY_PACKAGE, IDENTITY_BLUEPRINT, IDENTITY_CREATE_ADVANCED_IDENT) => {
906                    return DecompiledInstruction::new("CREATE_IDENTITY_ADVANCED");
907                }
908                (&IDENTITY_PACKAGE, IDENTITY_BLUEPRINT, IDENTITY_CREATE_IDENT) => {
909                    return DecompiledInstruction::new("CREATE_IDENTITY");
910                }
911                (
912                    &ACCESS_CONTROLLER_PACKAGE,
913                    ACCESS_CONTROLLER_BLUEPRINT,
914                    ACCESS_CONTROLLER_CREATE_IDENT,
915                ) => {
916                    return DecompiledInstruction::new("CREATE_ACCESS_CONTROLLER");
917                }
918                (
919                    &RESOURCE_PACKAGE,
920                    FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT,
921                    FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT,
922                ) => {
923                    return DecompiledInstruction::new("CREATE_FUNGIBLE_RESOURCE");
924                }
925                (
926                    &RESOURCE_PACKAGE,
927                    FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT,
928                    FUNGIBLE_RESOURCE_MANAGER_CREATE_WITH_INITIAL_SUPPLY_IDENT,
929                ) => {
930                    return DecompiledInstruction::new(
931                        "CREATE_FUNGIBLE_RESOURCE_WITH_INITIAL_SUPPLY",
932                    );
933                }
934                (
935                    &RESOURCE_PACKAGE,
936                    NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT,
937                    NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT,
938                ) => {
939                    return DecompiledInstruction::new("CREATE_NON_FUNGIBLE_RESOURCE");
940                }
941                (
942                    &RESOURCE_PACKAGE,
943                    NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT,
944                    NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_WITH_INITIAL_SUPPLY_IDENT,
945                ) => {
946                    return DecompiledInstruction::new(
947                        "CREATE_NON_FUNGIBLE_RESOURCE_WITH_INITIAL_SUPPLY",
948                    );
949                }
950                _ => {}
951            }
952        }
953        DecompiledInstruction::new(Self::IDENT)
954            .add_argument(&self.package_address)
955            .add_argument(&self.blueprint_name)
956            .add_argument(&self.function_name)
957    }
958}
959
960impl ManifestInstruction for CallFunction {
961    const IDENT: &'static str = "CALL_FUNCTION";
962    const ID: u8 = INSTRUCTION_CALL_FUNCTION_DISCRIMINATOR;
963
964    fn decompile(
965        &self,
966        _context: &mut DecompilationContext,
967    ) -> Result<DecompiledInstruction, DecompileError> {
968        self.decompile_header()
969            .add_separated_tuple_value_arguments(&self.args)
970    }
971
972    fn effect(&self) -> Effect {
973        Effect::Invocation {
974            kind: InvocationKind::Function {
975                address: &self.package_address,
976                blueprint: &self.blueprint_name,
977                function: &self.function_name,
978            },
979            args: &self.args,
980        }
981    }
982}
983
984#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
985pub struct CallMethod {
986    pub address: ManifestGlobalAddress,
987    pub method_name: String,
988    pub args: ManifestValue,
989}
990
991impl CallMethod {
992    fn decompile_header(&self) -> DecompiledInstruction {
993        if let ManifestGlobalAddress::Static(global_address) = &self.address {
994            match (global_address.as_node_id(), self.method_name.as_str()) {
995                (address, PACKAGE_CLAIM_ROYALTIES_IDENT) if address.is_global_package() => {
996                    return DecompiledInstruction::new("CLAIM_PACKAGE_ROYALTIES")
997                        .add_argument(global_address);
998                }
999                (address, FUNGIBLE_RESOURCE_MANAGER_MINT_IDENT)
1000                    if address.is_global_fungible_resource_manager() =>
1001                {
1002                    return DecompiledInstruction::new("MINT_FUNGIBLE")
1003                        .add_argument(global_address);
1004                }
1005                (address, NON_FUNGIBLE_RESOURCE_MANAGER_MINT_IDENT)
1006                    if address.is_global_non_fungible_resource_manager() =>
1007                {
1008                    return DecompiledInstruction::new("MINT_NON_FUNGIBLE")
1009                        .add_argument(global_address);
1010                }
1011                (address, NON_FUNGIBLE_RESOURCE_MANAGER_MINT_RUID_IDENT)
1012                    if address.is_global_non_fungible_resource_manager() =>
1013                {
1014                    return DecompiledInstruction::new("MINT_RUID_NON_FUNGIBLE")
1015                        .add_argument(global_address);
1016                }
1017                (address, CONSENSUS_MANAGER_CREATE_VALIDATOR_IDENT)
1018                    if address.is_global_consensus_manager() =>
1019                {
1020                    return DecompiledInstruction::new("CREATE_VALIDATOR");
1021                }
1022                _ => {}
1023            }
1024        }
1025        DecompiledInstruction::new(Self::IDENT)
1026            .add_argument(&self.address)
1027            .add_argument(&self.method_name)
1028    }
1029}
1030
1031impl ManifestInstruction for CallMethod {
1032    const IDENT: &'static str = "CALL_METHOD";
1033    const ID: u8 = INSTRUCTION_CALL_METHOD_DISCRIMINATOR;
1034
1035    fn decompile(
1036        &self,
1037        _context: &mut DecompilationContext,
1038    ) -> Result<DecompiledInstruction, DecompileError> {
1039        self.decompile_header()
1040            .add_separated_tuple_value_arguments(&self.args)
1041    }
1042
1043    fn effect(&self) -> Effect {
1044        Effect::Invocation {
1045            kind: InvocationKind::Method {
1046                address: &self.address,
1047                module_id: ModuleId::Main,
1048                method: &self.method_name,
1049            },
1050            args: &self.args,
1051        }
1052    }
1053}
1054
1055#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
1056pub struct CallRoyaltyMethod {
1057    pub address: ManifestGlobalAddress,
1058    pub method_name: String,
1059    pub args: ManifestValue,
1060}
1061
1062impl CallRoyaltyMethod {
1063    fn decompile_header(&self) -> DecompiledInstruction {
1064        match self.method_name.as_str() {
1065            COMPONENT_ROYALTY_SET_ROYALTY_IDENT => {
1066                return DecompiledInstruction::new("SET_COMPONENT_ROYALTY")
1067                    .add_argument(&self.address);
1068            }
1069            COMPONENT_ROYALTY_LOCK_ROYALTY_IDENT => {
1070                return DecompiledInstruction::new("LOCK_COMPONENT_ROYALTY")
1071                    .add_argument(&self.address);
1072            }
1073            COMPONENT_ROYALTY_CLAIM_ROYALTIES_IDENT => {
1074                return DecompiledInstruction::new("CLAIM_COMPONENT_ROYALTIES")
1075                    .add_argument(&self.address);
1076            }
1077            _ => {}
1078        }
1079        DecompiledInstruction::new(Self::IDENT)
1080            .add_argument(&self.address)
1081            .add_argument(&self.method_name)
1082    }
1083}
1084
1085impl ManifestInstruction for CallRoyaltyMethod {
1086    const IDENT: &'static str = "CALL_ROYALTY_METHOD";
1087    const ID: u8 = INSTRUCTION_CALL_ROYALTY_METHOD_DISCRIMINATOR;
1088
1089    fn decompile(
1090        &self,
1091        _context: &mut DecompilationContext,
1092    ) -> Result<DecompiledInstruction, DecompileError> {
1093        self.decompile_header()
1094            .add_separated_tuple_value_arguments(&self.args)
1095    }
1096
1097    fn effect(&self) -> Effect {
1098        Effect::Invocation {
1099            kind: InvocationKind::Method {
1100                address: &self.address,
1101                module_id: ModuleId::Royalty,
1102                method: &self.method_name,
1103            },
1104            args: &self.args,
1105        }
1106    }
1107}
1108
1109#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
1110pub struct CallMetadataMethod {
1111    pub address: ManifestGlobalAddress,
1112    pub method_name: String,
1113    pub args: ManifestValue,
1114}
1115
1116impl CallMetadataMethod {
1117    fn decompile_header(&self) -> DecompiledInstruction {
1118        match self.method_name.as_str() {
1119            METADATA_SET_IDENT => {
1120                return DecompiledInstruction::new("SET_METADATA").add_argument(&self.address);
1121            }
1122            METADATA_REMOVE_IDENT => {
1123                return DecompiledInstruction::new("REMOVE_METADATA").add_argument(&self.address);
1124            }
1125            METADATA_LOCK_IDENT => {
1126                return DecompiledInstruction::new("LOCK_METADATA").add_argument(&self.address);
1127            }
1128            _ => {}
1129        }
1130        DecompiledInstruction::new(Self::IDENT)
1131            .add_argument(&self.address)
1132            .add_argument(&self.method_name)
1133    }
1134}
1135
1136impl ManifestInstruction for CallMetadataMethod {
1137    const IDENT: &'static str = "CALL_METADATA_METHOD";
1138    const ID: u8 = INSTRUCTION_CALL_METADATA_METHOD_DISCRIMINATOR;
1139
1140    fn decompile(
1141        &self,
1142        _context: &mut DecompilationContext,
1143    ) -> Result<DecompiledInstruction, DecompileError> {
1144        self.decompile_header()
1145            .add_separated_tuple_value_arguments(&self.args)
1146    }
1147
1148    fn effect(&self) -> Effect {
1149        Effect::Invocation {
1150            kind: InvocationKind::Method {
1151                address: &self.address,
1152                module_id: ModuleId::Metadata,
1153                method: &self.method_name,
1154            },
1155            args: &self.args,
1156        }
1157    }
1158}
1159
1160#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
1161pub struct CallRoleAssignmentMethod {
1162    pub address: ManifestGlobalAddress,
1163    pub method_name: String,
1164    pub args: ManifestValue,
1165}
1166
1167impl CallRoleAssignmentMethod {
1168    fn decompile_header(&self) -> DecompiledInstruction {
1169        match self.method_name.as_str() {
1170            ROLE_ASSIGNMENT_SET_OWNER_IDENT => {
1171                return DecompiledInstruction::new("SET_OWNER_ROLE").add_argument(&self.address);
1172            }
1173            ROLE_ASSIGNMENT_LOCK_OWNER_IDENT => {
1174                return DecompiledInstruction::new("LOCK_OWNER_ROLE").add_argument(&self.address);
1175            }
1176            ROLE_ASSIGNMENT_SET_IDENT => {
1177                return DecompiledInstruction::new("SET_ROLE").add_argument(&self.address);
1178            }
1179            _ => {}
1180        }
1181        DecompiledInstruction::new(Self::IDENT)
1182            .add_argument(&self.address)
1183            .add_argument(&self.method_name)
1184    }
1185}
1186
1187impl ManifestInstruction for CallRoleAssignmentMethod {
1188    const IDENT: &'static str = "CALL_ROLE_ASSIGNMENT_METHOD";
1189    const ID: u8 = INSTRUCTION_CALL_ROLE_ASSIGNMENT_METHOD_DISCRIMINATOR;
1190
1191    fn decompile(
1192        &self,
1193        _context: &mut DecompilationContext,
1194    ) -> Result<DecompiledInstruction, DecompileError> {
1195        self.decompile_header()
1196            .add_separated_tuple_value_arguments(&self.args)
1197    }
1198
1199    fn effect(&self) -> Effect {
1200        Effect::Invocation {
1201            kind: InvocationKind::Method {
1202                address: &self.address,
1203                module_id: ModuleId::RoleAssignment,
1204                method: &self.method_name,
1205            },
1206            args: &self.args,
1207        }
1208    }
1209}
1210
1211#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
1212pub struct CallDirectVaultMethod {
1213    pub address: InternalAddress,
1214    pub method_name: String,
1215    pub args: ManifestValue,
1216}
1217
1218impl CallDirectVaultMethod {
1219    fn decompile_header(&self) -> DecompiledInstruction {
1220        match self.method_name.as_str() {
1221            VAULT_RECALL_IDENT => {
1222                return DecompiledInstruction::new("RECALL_FROM_VAULT").add_argument(&self.address);
1223            }
1224            VAULT_FREEZE_IDENT => {
1225                return DecompiledInstruction::new("FREEZE_VAULT").add_argument(&self.address);
1226            }
1227            VAULT_UNFREEZE_IDENT => {
1228                return DecompiledInstruction::new("UNFREEZE_VAULT").add_argument(&self.address);
1229            }
1230            NON_FUNGIBLE_VAULT_RECALL_NON_FUNGIBLES_IDENT => {
1231                return DecompiledInstruction::new("RECALL_NON_FUNGIBLES_FROM_VAULT")
1232                    .add_argument(&self.address);
1233            }
1234            _ => {}
1235        }
1236        DecompiledInstruction::new(Self::IDENT)
1237            .add_argument(&self.address)
1238            .add_argument(&self.method_name)
1239    }
1240}
1241
1242impl ManifestInstruction for CallDirectVaultMethod {
1243    const IDENT: &'static str = "CALL_DIRECT_VAULT_METHOD";
1244    const ID: u8 = INSTRUCTION_CALL_DIRECT_VAULT_METHOD_DISCRIMINATOR;
1245
1246    fn decompile(
1247        &self,
1248        _context: &mut DecompilationContext,
1249    ) -> Result<DecompiledInstruction, DecompileError> {
1250        self.decompile_header()
1251            .add_separated_tuple_value_arguments(&self.args)
1252    }
1253
1254    fn effect(&self) -> Effect {
1255        Effect::Invocation {
1256            kind: InvocationKind::DirectMethod {
1257                address: &self.address,
1258                method: &self.method_name,
1259            },
1260            args: &self.args,
1261        }
1262    }
1263}
1264
1265//======================================================================
1266// region:Address Allocation
1267//======================================================================
1268
1269/// Preallocates a global address for an object of the given blueprint.
1270/// The package address and blueprint name must be provided, followed
1271/// by a new `AddressReservation("name")` and a new `NamedAddress("name")`.
1272///
1273/// The address reservation can be passed into a constructor to be used
1274/// to create the object at that address. The named address can be
1275/// used in the place of another address in an invocation or other
1276/// manifest instruction.
1277#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
1278pub struct AllocateGlobalAddress {
1279    pub package_address: PackageAddress,
1280    pub blueprint_name: String,
1281}
1282
1283impl ManifestInstruction for AllocateGlobalAddress {
1284    const IDENT: &'static str = "ALLOCATE_GLOBAL_ADDRESS";
1285    const ID: u8 = INSTRUCTION_ALLOCATE_GLOBAL_ADDRESS_DISCRIMINATOR;
1286
1287    fn decompile(
1288        &self,
1289        context: &mut DecompilationContext,
1290    ) -> Result<DecompiledInstruction, DecompileError> {
1291        let instruction = DecompiledInstruction::new(Self::IDENT)
1292            .add_argument(&self.package_address)
1293            .add_argument(&self.blueprint_name)
1294            .add_argument(context.new_address_reservation())
1295            .add_argument(context.new_address());
1296        Ok(instruction)
1297    }
1298
1299    fn effect(&self) -> Effect {
1300        Effect::CreateAddressAndReservation {
1301            package_address: &self.package_address,
1302            blueprint_name: &self.blueprint_name,
1303        }
1304    }
1305}
1306
1307//======================================================================
1308// region:Interactions with other intents
1309//======================================================================
1310
1311/// This instruction is only allowed in subintent manifests. It passes
1312/// control to a parent intent, and takes an optional list of arguments,
1313/// to enable passing buckets to the parent intent. Other objects are not
1314/// allowed to be passed.
1315///
1316/// Every subintent must end with a `YIELD_TO_PARENT` to end the subintent
1317/// and return constrol to the parent intent.
1318///
1319/// `YIELD_TO_PARENT` instructions which are not at the end of the subintent
1320/// instead temporarily pause execution, and hand over control to the parent.
1321/// Control is resumed when the parent intent calls `YIELD_TO_CHILD` on this subintent.
1322///
1323/// The validation and runtime guarantee that all subintents are run to
1324/// completion by their parents.
1325#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
1326pub struct YieldToParent {
1327    pub args: ManifestValue,
1328}
1329
1330impl YieldToParent {
1331    pub fn empty() -> Self {
1332        Self {
1333            args: ManifestValue::unit(),
1334        }
1335    }
1336}
1337
1338impl ManifestInstruction for YieldToParent {
1339    const IDENT: &'static str = "YIELD_TO_PARENT";
1340    const ID: u8 = INSTRUCTION_YIELD_TO_PARENT_DISCRIMINATOR;
1341
1342    fn decompile(
1343        &self,
1344        _context: &mut DecompilationContext,
1345    ) -> Result<DecompiledInstruction, DecompileError> {
1346        DecompiledInstruction::new(Self::IDENT).add_separated_tuple_value_arguments(&self.args)
1347    }
1348
1349    fn effect(&self) -> Effect {
1350        Effect::Invocation {
1351            kind: InvocationKind::YieldToParent,
1352            args: &self.args,
1353        }
1354    }
1355}
1356
1357/// This instruction passes control to the given child subintent.
1358/// It takes an optional list of arguments, to enable passing buckets to
1359/// the child subintent. Other objects are not allowed to be passed.
1360///
1361/// `YIELD_TO_CHILD` instructions temporarily pause execution, and
1362/// hand over control to the child. Control is resumed when the child
1363/// subintent calls `YIELD_TO_PARENT`.
1364///
1365/// The validation and runtime guarantee that subintents end with a
1366/// `YIELD_TO_PARENT`, and that the number of `YIELD_TO_PARENT` calls in
1367/// a child matches the number of `YIELD_TO_CHILD` calls in the parent.
1368#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
1369pub struct YieldToChild {
1370    /// Ideally this would be a ManifestNamedIntent - but there wasn't time
1371    /// to version ManifestSbor and add this in - so instead, we use a raw u32
1372    /// here.
1373    pub child_index: ManifestNamedIntentIndex,
1374    pub args: ManifestValue,
1375}
1376
1377impl ManifestInstruction for YieldToChild {
1378    const IDENT: &'static str = "YIELD_TO_CHILD";
1379    const ID: u8 = INSTRUCTION_YIELD_TO_CHILD_DISCRIMINATOR;
1380
1381    fn decompile(
1382        &self,
1383        context: &mut DecompilationContext,
1384    ) -> Result<DecompiledInstruction, DecompileError> {
1385        let intent_name = context.object_names.intent_name(self.child_index.into());
1386        DecompiledInstruction::new(Self::IDENT)
1387            .add_raw_argument(format!("NamedIntent(\"{intent_name}\")"))
1388            .add_separated_tuple_value_arguments(&self.args)
1389    }
1390
1391    fn effect(&self) -> Effect {
1392        Effect::Invocation {
1393            kind: InvocationKind::YieldToChild {
1394                child_index: self.child_index.into(),
1395            },
1396            args: &self.args,
1397        }
1398    }
1399}
1400
1401/// This instruction is used to run an access rule assertion against
1402/// the parent manifest's auth zone.
1403///
1404/// This can be used by a subintent to perform a counterparty check,
1405/// to ensure their subintent can only be directly used by a particular
1406/// counterparty.
1407#[derive(Debug, Clone, PartialEq, Eq, ManifestSbor, ScryptoDescribe)]
1408pub struct VerifyParent {
1409    pub access_rule: AccessRule,
1410}
1411
1412impl ManifestInstruction for VerifyParent {
1413    const IDENT: &'static str = "VERIFY_PARENT";
1414    const ID: u8 = INSTRUCTION_VERIFY_PARENT_DISCRIMINATOR;
1415
1416    fn decompile(
1417        &self,
1418        _context: &mut DecompilationContext,
1419    ) -> Result<DecompiledInstruction, DecompileError> {
1420        let instruction = DecompiledInstruction::new(Self::IDENT).add_argument(&self.access_rule);
1421        Ok(instruction)
1422    }
1423
1424    fn effect(&self) -> Effect {
1425        Effect::Verification {
1426            verification: VerificationKind::Parent,
1427            access_rule: &self.access_rule,
1428        }
1429    }
1430}
1431
1432//===============================================================
1433// region:Discriminators
1434//===============================================================
1435// These discriminators have to be constant, but have been regrouped
1436// below into a more logical grouping, to put similar instructions
1437// together.
1438//===============================================================
1439
1440//==============
1441// Bucket Lifecycle
1442//==============
1443const INSTRUCTION_TAKE_FROM_WORKTOP_DISCRIMINATOR: u8 = 0x00;
1444const INSTRUCTION_TAKE_NON_FUNGIBLES_FROM_WORKTOP_DISCRIMINATOR: u8 = 0x01;
1445const INSTRUCTION_TAKE_ALL_FROM_WORKTOP_DISCRIMINATOR: u8 = 0x02;
1446const INSTRUCTION_RETURN_TO_WORKTOP_DISCRIMINATOR: u8 = 0x03;
1447const INSTRUCTION_BURN_RESOURCE_DISCRIMINATOR: u8 = 0x24;
1448
1449//==============
1450// Resource Assertions
1451//==============
1452const INSTRUCTION_ASSERT_WORKTOP_CONTAINS_DISCRIMINATOR: u8 = 0x04;
1453const INSTRUCTION_ASSERT_WORKTOP_CONTAINS_NON_FUNGIBLES_DISCRIMINATOR: u8 = 0x05;
1454const INSTRUCTION_ASSERT_WORKTOP_CONTAINS_ANY_DISCRIMINATOR: u8 = 0x06;
1455
1456const INSTRUCTION_ASSERT_WORKTOP_RESOURCES_ONLY_DISCRIMINATOR: u8 = 0x08;
1457const INSTRUCTION_ASSERT_WORKTOP_RESOURCES_INCLUDE_DISCRIMINATOR: u8 = 0x09;
1458const INSTRUCTION_ASSERT_NEXT_CALL_RETURNS_ONLY_DISCRIMINATOR: u8 = 0x0A;
1459const INSTRUCTION_ASSERT_NEXT_CALL_RETURNS_INCLUDE_DISCRIMINATOR: u8 = 0x0B;
1460const INSTRUCTION_ASSERT_BUCKET_CONTENTS_DISCRIMINATOR: u8 = 0x0C;
1461
1462//==============
1463// Proof Lifecycle
1464//==============
1465const INSTRUCTION_CREATE_PROOF_FROM_BUCKET_OF_AMOUNT_DISCRIMINATOR: u8 = 0x21;
1466const INSTRUCTION_CREATE_PROOF_FROM_BUCKET_OF_NON_FUNGIBLES_DISCRIMINATOR: u8 = 0x22;
1467const INSTRUCTION_CREATE_PROOF_FROM_BUCKET_OF_ALL_DISCRIMINATOR: u8 = 0x23;
1468
1469const INSTRUCTION_CREATE_PROOF_FROM_AUTH_ZONE_OF_AMOUNT_DISCRIMINATOR: u8 = 0x14;
1470const INSTRUCTION_CREATE_PROOF_FROM_AUTH_ZONE_OF_NON_FUNGIBLES_DISCRIMINATOR: u8 = 0x15;
1471const INSTRUCTION_CREATE_PROOF_FROM_AUTH_ZONE_OF_ALL_DISCRIMINATOR: u8 = 0x16;
1472
1473const INSTRUCTION_CLONE_PROOF_DISCRIMINATOR: u8 = 0x30;
1474const INSTRUCTION_DROP_PROOF_DISCRIMINATOR: u8 = 0x31;
1475
1476const INSTRUCTION_POP_FROM_AUTH_ZONE_DISCRIMINATOR: u8 = 0x10;
1477const INSTRUCTION_PUSH_TO_AUTH_ZONE_DISCRIMINATOR: u8 = 0x11;
1478
1479const INSTRUCTION_DROP_AUTH_ZONE_PROOFS_DISCRIMINATOR: u8 = 0x12;
1480const INSTRUCTION_DROP_AUTH_ZONE_REGULAR_PROOFS_DISCRIMINATOR: u8 = 0x13;
1481const INSTRUCTION_DROP_AUTH_ZONE_SIGNATURE_PROOFS_DISCRIMINATOR: u8 = 0x17;
1482
1483const INSTRUCTION_DROP_NAMED_PROOFS_DISCRIMINATOR: u8 = 0x52;
1484const INSTRUCTION_DROP_ALL_PROOFS_DISCRIMINATOR: u8 = 0x50;
1485
1486//==============
1487// Invocation
1488//==============
1489const INSTRUCTION_CALL_FUNCTION_DISCRIMINATOR: u8 = 0x40;
1490const INSTRUCTION_CALL_METHOD_DISCRIMINATOR: u8 = 0x41;
1491const INSTRUCTION_CALL_ROYALTY_METHOD_DISCRIMINATOR: u8 = 0x42;
1492const INSTRUCTION_CALL_METADATA_METHOD_DISCRIMINATOR: u8 = 0x43;
1493const INSTRUCTION_CALL_ROLE_ASSIGNMENT_METHOD_DISCRIMINATOR: u8 = 0x44;
1494const INSTRUCTION_CALL_DIRECT_VAULT_METHOD_DISCRIMINATOR: u8 = 0x45;
1495
1496//==============
1497// Address Allocation
1498//==============
1499const INSTRUCTION_ALLOCATE_GLOBAL_ADDRESS_DISCRIMINATOR: u8 = 0x51;
1500
1501//==============
1502// Interactions with other intents
1503//==============
1504const INSTRUCTION_YIELD_TO_PARENT_DISCRIMINATOR: u8 = 0x60;
1505const INSTRUCTION_YIELD_TO_CHILD_DISCRIMINATOR: u8 = 0x61;
1506const INSTRUCTION_VERIFY_PARENT_DISCRIMINATOR: u8 = 0x62;