@@ -29,6 +29,7 @@ import (
29
29
"testing"
30
30
"time"
31
31
32
+ "github.com/celo-org/celo-blockchain/accounts/abi"
32
33
"github.com/celo-org/celo-blockchain/common"
33
34
"github.com/celo-org/celo-blockchain/common/hexutil"
34
35
"github.com/celo-org/celo-blockchain/consensus"
@@ -544,6 +545,194 @@ func TestTraceTransactionWithRegistryDeployed(t *testing.T) {
544
545
}
545
546
}
546
547
548
+ // Use the callTracer to trace a native CELO transfer after the
549
+ // registry has been deployed, as above.
550
+ func TestCallTraceTransactionNativeTransfer (t * testing.T ) {
551
+ t .Parallel ()
552
+
553
+ // Initialize test accounts
554
+ accounts := newAccounts (2 )
555
+ genesis := & core.Genesis {Alloc : core.GenesisAlloc {
556
+ accounts [0 ].addr : {Balance : big .NewInt (params .Ether )},
557
+ accounts [1 ].addr : {Balance : big .NewInt (params .Ether )},
558
+ common .HexToAddress ("0xce10" ): { // Registry Proxy
559
+ Code : testutil .RegistryProxyOpcodes ,
560
+ Storage : map [common.Hash ]common.Hash {
561
+ // Hashes represent the storage slot for Registry.sol's `registry` mapping
562
+ // which is stored in the RegistryProxy's storage.
563
+ // Hashes are computed by taking: keccack(packed(params.GoldTokenRegistryId, 1)),
564
+ // where 1 is the storage offset)
565
+ common .HexToHash ("0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" ): common .HexToHash ("0xce11" ), // Registry Implementation
566
+ common .HexToHash ("0x91646b8507bf2e54d7c3de9155442ba111546b81af1cbdd1f68eeb6926b98d58" ): common .HexToHash ("0xd023" ), // Governance Proxy
567
+ },
568
+ Balance : big .NewInt (0 ),
569
+ },
570
+ common .HexToAddress ("0xce11" ): { // Registry Implementation
571
+ Code : testutil .RegistryOpcodes ,
572
+ Balance : big .NewInt (0 ),
573
+ },
574
+ }}
575
+
576
+ target := common.Hash {}
577
+ signer := types.HomesteadSigner {}
578
+ transferVal := big .NewInt (1000 )
579
+ api := NewAPI (newTestBackend (t , 1 , genesis , func (i int , b * core.BlockGen ) {
580
+ // Transfer from account[0] to account[1]
581
+ // value: 1000 wei
582
+ // fee: 0 wei
583
+ tx , _ := types .SignTx (types .NewTransaction (uint64 (i ), accounts [1 ].addr , transferVal , params .TxGas , nil , nil , nil , nil , nil ), signer , accounts [0 ].key )
584
+ b .AddTx (tx )
585
+ target = tx .Hash ()
586
+ }))
587
+ tracerStr := "callTracer"
588
+ result , err := api .TraceTransaction (context .Background (), target , & TraceConfig {Tracer : & tracerStr })
589
+ if err != nil {
590
+ t .Errorf ("Failed to trace transaction %v" , err )
591
+ }
592
+
593
+ ret := new (callTrace )
594
+ if err := json .Unmarshal (result .(json.RawMessage ), ret ); err != nil {
595
+ t .Fatalf ("failed to unmarshal trace result: %v" , err )
596
+ }
597
+ expectedTrace := & callTrace {
598
+ Type : "CALL" ,
599
+ From : accounts [0 ].addr ,
600
+ To : accounts [1 ].addr ,
601
+ Input : hexutil .Bytes (common .Hex2Bytes ("0x" )),
602
+ Output : hexutil .Bytes (common .Hex2Bytes ("0x" )),
603
+ Gas : newRPCUint64 (0 ),
604
+ GasUsed : newRPCUint64 (0 ),
605
+ Value : (* hexutil .Big )(transferVal ),
606
+ }
607
+ if ! jsonEqual (ret , expectedTrace ) {
608
+ t .Fatalf ("trace mismatch: \n have %+v\n want %+v" , ret , expectedTrace )
609
+ }
610
+ }
611
+
612
+ // Use the callTracer to trace a CELO transfer made via the transfer
613
+ // precompile (by sending this from the registered GoldToken contract).
614
+ func TestCallTraceTransactionPrecompileTransfer (t * testing.T ) {
615
+ // Invoke the transfer precompile by sending a transfer from an account
616
+ // registered as GoldToken in the mock registry
617
+ t .Parallel ()
618
+ // Initialize test accounts
619
+ accounts := newAccounts (3 )
620
+ goldToken := accounts [0 ]
621
+ registryProxyAddr := common .HexToAddress ("0xce10" )
622
+ registryImplAddr := common .HexToAddress ("0xce11" )
623
+ genesis := & core.Genesis {Alloc : core.GenesisAlloc {
624
+ goldToken .addr : {Balance : big .NewInt (params .Ether )},
625
+ accounts [1 ].addr : {Balance : big .NewInt (params .Ether )},
626
+ accounts [2 ].addr : {Balance : big .NewInt (params .Ether )},
627
+ registryProxyAddr : { // Registry Proxy
628
+ Code : testutil .RegistryProxyOpcodes ,
629
+ Storage : map [common.Hash ]common.Hash {
630
+ common .HexToHash ("0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" ): common .HexToHash ("0xce11" ), // Registry Implementation
631
+ common .HexToHash ("0x91646b8507bf2e54d7c3de9155442ba111546b81af1cbdd1f68eeb6926b98d58" ): common .HexToHash ("0xd023" ), // Governance Proxy
632
+ common .HexToHash ("0x773cc8652456781771d48fb3d560d7ba3d6d1882654492b68beec583d2c590aa" ): goldToken .addr .Hash (), // GoldToken Implementation
633
+ common .HexToHash ("0x2131a4338f6fb8d4507e234a7c72af8efefbbf2f1817ed570bce33eb6667feb9" ): common .HexToHash ("0xd007" ), // Reserve Implementation
634
+ },
635
+ Balance : big .NewInt (0 ),
636
+ },
637
+ registryImplAddr : { // Registry Implementation
638
+ Code : testutil .RegistryOpcodes ,
639
+ Balance : big .NewInt (0 ),
640
+ },
641
+ }}
642
+
643
+ target := common.Hash {}
644
+ signer := types.HomesteadSigner {}
645
+ transferVal := big .NewInt (1000 )
646
+
647
+ // Construct and pack data for transfer precompile representing [from, to, value]
648
+ addressTy , err := abi .NewType ("address" , "" , nil )
649
+ if err != nil {
650
+ t .Fatalf ("failed to create address type: %v" , err )
651
+ }
652
+ uint256Ty , err := abi .NewType ("uint256" , "" , nil )
653
+ if err != nil {
654
+ t .Fatalf ("failed to create uint256 type: %v" , err )
655
+ }
656
+
657
+ transferArgs := abi.Arguments {
658
+ {
659
+ Type : addressTy ,
660
+ },
661
+ {
662
+ Type : addressTy ,
663
+ },
664
+ {
665
+ Type : uint256Ty ,
666
+ },
667
+ }
668
+ data , err := transferArgs .Pack (accounts [1 ].addr , accounts [2 ].addr , transferVal )
669
+ if err != nil {
670
+ t .Fatalf ("failed to pack args: %v" , err )
671
+ }
672
+ transferPrecompile := common .HexToAddress ("0xfd" )
673
+ gas := params .TxGas * 2
674
+ api := NewAPI (newTestBackend (t , 1 , genesis , func (i int , b * core.BlockGen ) {
675
+ // Transfer via transfer precompile by sending tx from GoldToken addr
676
+ tx , _ := types .SignTx (types .NewTransaction (uint64 (i ), transferPrecompile , big .NewInt (0 ), gas , big .NewInt (3 ), nil , nil , nil , data ), signer , goldToken .key )
677
+ b .AddTx (tx )
678
+ target = tx .Hash ()
679
+ }))
680
+ tracerStr := "callTracer"
681
+ result , err := api .TraceTransaction (context .Background (), target , & TraceConfig {Tracer : & tracerStr })
682
+
683
+ if err != nil {
684
+ t .Errorf ("Failed to trace transaction %v" , err )
685
+ }
686
+
687
+ ret := new (callTrace )
688
+ if err := json .Unmarshal (result .(json.RawMessage ), ret ); err != nil {
689
+ t .Fatalf ("failed to unmarshal trace result: %v" , err )
690
+ }
691
+
692
+ // Registry ABI packed version of Registry.getAddressFor("GoldToken")
693
+ packedGetAddressForGoldToken := common .FromHex ("0xdd927233d7e89ade8430819f08bf97a087285824af3351ee12d72a2d132b0c6c0687bfaf" )
694
+ expectedTrace := & callTrace {
695
+ // Outer transaction call
696
+ Type : "CALL" ,
697
+ From : goldToken .addr ,
698
+ To : transferPrecompile ,
699
+ Input : data ,
700
+ Output : data ,
701
+ Gas : newRPCUint64 (20112 ),
702
+ // Note that top-level traces do not currently include intrinsic gas
703
+ GasUsed : newRPCUint64 (params .CallValueTransferGas ),
704
+ Value : (* hexutil .Big )(big .NewInt (0 )),
705
+ Calls : []callTrace {
706
+ {
707
+ // Lookup of GoldToken contract address with capped gas
708
+ Type : "STATICCALL" ,
709
+ From : common .ZeroAddress ,
710
+ To : registryProxyAddr ,
711
+ Input : packedGetAddressForGoldToken ,
712
+ Output : common .LeftPadBytes (goldToken .addr .Bytes (), 32 ),
713
+ Gas : newRPCUint64 (params .MaxGasForGetAddressFor ),
714
+ GasUsed : newRPCUint64 (0 ),
715
+ Calls : []callTrace {
716
+ {
717
+ // RegistryProxy -> RegistryImpl delegate call to
718
+ // retrieve GoldToken address
719
+ Type : "DELEGATECALL" ,
720
+ From : registryProxyAddr ,
721
+ To : registryImplAddr ,
722
+ Input : packedGetAddressForGoldToken ,
723
+ Output : common .LeftPadBytes (goldToken .addr .Bytes (), 32 ),
724
+ Gas : newRPCUint64 (0 ),
725
+ GasUsed : newRPCUint64 (0 ),
726
+ },
727
+ },
728
+ },
729
+ },
730
+ }
731
+ if ! jsonEqual (ret , expectedTrace ) {
732
+ t .Fatalf ("trace mismatch: \n have %+v\n want %+v" , ret , expectedTrace )
733
+ }
734
+ }
735
+
547
736
func TestTraceBlock (t * testing.T ) {
548
737
t .Parallel ()
549
738
0 commit comments