@@ -2,7 +2,11 @@ use std::rc::Rc;
2
2
use std:: sync:: Arc ;
3
3
4
4
use everscale_types:: error:: Error ;
5
- use everscale_types:: models:: { BlockchainConfigParams , CurrencyCollection , IntAddr } ;
5
+ use everscale_types:: error:: Error :: InvalidData ;
6
+ use everscale_types:: models:: {
7
+ BlockchainConfigParams , CurrencyCollection , ExtInMsgInfo , IntAddr , IntMsgInfo , MsgInfo ,
8
+ OwnedMessage ,
9
+ } ;
6
10
use everscale_types:: num:: Tokens ;
7
11
use everscale_types:: prelude:: * ;
8
12
use num_bigint:: { BigInt , Sign } ;
@@ -480,6 +484,13 @@ impl SmcInfoTonV9 {
480
484
// ..base:SmcInfoTonV6
481
485
self . base . write_items ( items) ;
482
486
}
487
+
488
+ pub fn require_ton_v11 ( self ) -> SmcInfoTonV11 {
489
+ SmcInfoTonV11 {
490
+ base : self ,
491
+ in_msg : None ,
492
+ }
493
+ }
483
494
}
484
495
485
496
impl SmcInfo for SmcInfoTonV9 {
@@ -495,9 +506,9 @@ impl SmcInfo for SmcInfoTonV9 {
495
506
}
496
507
497
508
#[ derive( Default , Debug , Clone ) ]
498
- #[ repr( transparent) ]
499
509
pub struct SmcInfoTonV11 {
500
510
pub base : SmcInfoTonV9 ,
511
+ pub in_msg : Option < SafeRc < Tuple > > ,
501
512
}
502
513
503
514
impl SmcInfoTonV11 {
@@ -507,6 +518,138 @@ impl SmcInfoTonV11 {
507
518
fn write_items ( & self , items : & mut Tuple ) {
508
519
// ..base:SmcInfoTonV9
509
520
self . base . write_items ( items) ;
521
+ let message_value = match & self . in_msg {
522
+ Some ( message) => message. clone ( ) . into_dyn_value ( ) ,
523
+ None => Self :: prepare_empty_msg_tuple ( ) . into_dyn_value ( ) ,
524
+ } ;
525
+
526
+ items. push ( message_value) ;
527
+ }
528
+
529
+ pub fn with_in_message ( mut self , msg_cell_opt : Option < & Cell > ) -> Result < Self , Error > {
530
+ let Some ( msg) = msg_cell_opt else {
531
+ return Ok ( self ) ;
532
+ } ;
533
+
534
+ let message = OwnedMessage :: load_from ( & mut msg. as_slice ( ) ?) ?;
535
+
536
+ if message. info . is_external_out ( ) {
537
+ return Err ( InvalidData ) ;
538
+ }
539
+
540
+ let state_init_opt = match message. init {
541
+ Some ( init) => Some ( CellBuilder :: build_from ( init) ?) ,
542
+ None => None ,
543
+ } ;
544
+
545
+ let balance = self . base . base . base . message_balance . clone ( ) ;
546
+ let params_tuple = match message. info {
547
+ MsgInfo :: Int ( info) => {
548
+ Self :: prepare_internal_in_msg_tuple ( info, state_init_opt, balance) ?
549
+ }
550
+ MsgInfo :: ExtIn ( info) => {
551
+ Self :: prepare_external_in_msg_tuple ( info, state_init_opt, balance) ?
552
+ }
553
+ _ => unreachable ! ( ) ,
554
+ } ;
555
+
556
+ self . in_msg = Some ( params_tuple) ;
557
+ Ok ( self )
558
+ }
559
+
560
+ fn prepare_internal_in_msg_tuple (
561
+ msg : IntMsgInfo ,
562
+ state_init : Option < Cell > ,
563
+ msg_balance_remaining : CurrencyCollection ,
564
+ ) -> Result < SafeRc < Tuple > , Error > {
565
+ let address = OwnedCellSlice :: new_allow_exotic ( CellBuilder :: build_from ( msg. src ) ?) ;
566
+ let extra_currency = if msg_balance_remaining. other . is_empty ( ) {
567
+ Stack :: make_null ( )
568
+ } else {
569
+ SafeRc :: new_dyn_value ( CellBuilder :: build_from ( msg_balance_remaining. other ) ?)
570
+ } ;
571
+
572
+ let state_init = match state_init {
573
+ Some ( state_init) => SafeRc :: new_dyn_value ( state_init) ,
574
+ None => Stack :: make_null ( ) ,
575
+ } ;
576
+
577
+ let tuple = tuple ! [
578
+ int if msg. bounce { -1 } else { 0 } ,
579
+ int if msg. bounced { -1 } else { 0 } ,
580
+ slice address,
581
+ int msg. fwd_fee. into_inner( ) ,
582
+ int msg. created_lt,
583
+ int msg. created_at,
584
+ int msg. value. tokens. into_inner( ) ,
585
+ int msg_balance_remaining. tokens. into_inner( ) ,
586
+ raw extra_currency,
587
+ raw state_init
588
+ ] ;
589
+
590
+ Ok ( SafeRc :: new ( tuple) )
591
+ }
592
+
593
+ fn prepare_external_in_msg_tuple (
594
+ msg : ExtInMsgInfo ,
595
+ state_init : Option < Cell > ,
596
+ msg_balance_remaining : CurrencyCollection ,
597
+ ) -> Result < SafeRc < Tuple > , Error > {
598
+ let src_address = Self :: make_none_addr_slice ( ) ;
599
+ let extra_currency = if msg_balance_remaining. other . is_empty ( ) {
600
+ Stack :: make_null ( )
601
+ } else {
602
+ SafeRc :: new_dyn_value ( CellBuilder :: build_from ( msg_balance_remaining. other ) ?)
603
+ } ;
604
+
605
+ let state_init = match state_init {
606
+ Some ( state_init) => SafeRc :: new_dyn_value ( state_init) ,
607
+ None => Stack :: make_null ( ) ,
608
+ } ;
609
+
610
+ let tuple = tuple ! [
611
+ int 0 ,
612
+ int 0 ,
613
+ slice src_address,
614
+ int msg. import_fee. into_inner( ) ,
615
+ int 0 ,
616
+ int 0 ,
617
+ int 0 ,
618
+ int msg_balance_remaining. tokens. into_inner( ) ,
619
+ raw extra_currency,
620
+ raw state_init
621
+ ] ;
622
+
623
+ Ok ( SafeRc :: new ( tuple) )
624
+ }
625
+
626
+ fn prepare_empty_msg_tuple ( ) -> SafeRc < Tuple > {
627
+ let src_address = Self :: make_none_addr_slice ( ) ;
628
+
629
+ let tuple = tuple ! [
630
+ int 0 , //bounce
631
+ int 0 , //bounced
632
+ slice src_address, //src_addr
633
+ int 0 , //fwd fee
634
+ int 0 , //created lt
635
+ int 0 , //created at,
636
+ int 0 , //original value,
637
+ int 0 , // value,
638
+ null, //extra currency
639
+ null //state init
640
+ ] ;
641
+
642
+ SafeRc :: new ( tuple)
643
+ }
644
+
645
+ fn make_none_addr_slice ( ) -> OwnedCellSlice {
646
+ let mut addr_builder = CellBuilder :: new ( ) ;
647
+ addr_builder. store_zeros ( 2 ) . expect ( "can't fail" ) ;
648
+ OwnedCellSlice :: new_allow_exotic (
649
+ addr_builder
650
+ . build ( )
651
+ . expect ( "2 bits are valid input for empty builder" ) ,
652
+ )
510
653
}
511
654
}
512
655
0 commit comments