github.com/klaytn/klaytn@v1.10.2/blockchain/vm/internaltx_trace_json_test.go (about)

     1  // Modifications Copyright 2020 The klaytn Authors
     2  // Copyright 2017 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // InternalTxTracer is a full blown transaction tracer that extracts and reports all
    19  // the internal calls made by a transaction, along with any useful information.
    20  //
    21  // This file is derived from eth/tracers/internal/tracers/call_tracer.js (2018/06/04).
    22  // Modified and improved for the klaytn development.
    23  
    24  package vm
    25  
    26  import (
    27  	"bytes"
    28  	"encoding/json"
    29  	"reflect"
    30  	"testing"
    31  	"time"
    32  
    33  	"github.com/stretchr/testify/assert"
    34  
    35  	"github.com/klaytn/klaytn/common"
    36  )
    37  
    38  func jsonMustCompact(data []byte) []byte {
    39  	compactedBuffer := new(bytes.Buffer)
    40  	err := json.Compact(compactedBuffer, data)
    41  	if err != nil {
    42  		panic(err)
    43  	}
    44  	return compactedBuffer.Bytes()
    45  }
    46  
    47  func genAddressPtr(addr string) *common.Address {
    48  	ret := common.HexToAddress(addr)
    49  	return &ret
    50  }
    51  
    52  func TestInternalTxTrace_MarshalJSON(t *testing.T) {
    53  	type fields struct {
    54  		Type     string
    55  		From     *common.Address
    56  		To       *common.Address
    57  		Value    string
    58  		Gas      uint64
    59  		GasUsed  uint64
    60  		Input    string
    61  		Output   string
    62  		Error    error
    63  		Time     time.Duration
    64  		Calls    []*InternalTxTrace
    65  		Reverted *RevertedInfo
    66  	}
    67  	tests := []struct {
    68  		name   string
    69  		fields fields
    70  		want   []byte
    71  	}{
    72  		{
    73  			name: "revert_test",
    74  			fields: fields{
    75  				Type:    CALL.String(),
    76  				From:    genAddressPtr("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"),
    77  				To:      genAddressPtr("0xabbcd5b340c80b5f1c0545c04c987b87310296ae"),
    78  				Value:   "0x0",
    79  				Gas:     2971112,
    80  				GasUsed: 195,
    81  				Input:   "0x73b40a5c000000000000000000000000400de2e016bda6577407dfc379faba9899bc73ef0000000000000000000000002cc31912b2b0f3075a87b3640923d45a26cef3ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d79d8e6c7265636f76657279416464726573730000000000000000000000000000000000000000000000000000000000383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988383e3ec32dc0f66d8fe60dbdc2f6815bdf73a98800000000000000000000000000000000000000000000000000000000000000000000000000000000",
    82  				Error:   errExecutionReverted,
    83  				Reverted: &RevertedInfo{
    84  					Contract: genAddressPtr("0xabbcd5b340c80b5f1c0545c04c987b87310296ae"),
    85  				},
    86  			},
    87  			want: jsonMustCompact([]byte(`{
    88  	"type": "CALL",
    89  	"from": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
    90  	"to": "0xabbcd5b340c80b5f1c0545c04c987b87310296ae",
    91  	"value": "0x0",
    92      "gas": "0x2d55e8",
    93      "gasUsed": "0xc3",
    94      "input": "0x73b40a5c000000000000000000000000400de2e016bda6577407dfc379faba9899bc73ef0000000000000000000000002cc31912b2b0f3075a87b3640923d45a26cef3ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d79d8e6c7265636f76657279416464726573730000000000000000000000000000000000000000000000000000000000383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988383e3ec32dc0f66d8fe60dbdc2f6815bdf73a98800000000000000000000000000000000000000000000000000000000000000000000000000000000",
    95      "error": "execution reverted",
    96      "reverted": {
    97        "contract": "0xabbcd5b340c80b5f1c0545c04c987b87310296ae"
    98      }
    99    }`)),
   100  		},
   101  		{
   102  			name: "delegatecall_test",
   103  			fields: fields{
   104  				Type:    DELEGATECALL.String(),
   105  				From:    genAddressPtr("0x2074f91470365144df78c333948814fe4158af5a"),
   106  				To:      genAddressPtr("0x13cf0d18bcb898efd4e85ae2bb65a443ab86023c"),
   107  				Gas:     179,
   108  				GasUsed: 122,
   109  				Input:   "0xc605f76c",
   110  				Output:  "0x",
   111  			},
   112  			want: jsonMustCompact([]byte(`{
   113  		"type": "DELEGATECALL",
   114          "from": "0x2074f91470365144df78c333948814fe4158af5a",
   115  		"to": "0x13cf0d18bcb898efd4e85ae2bb65a443ab86023c",
   116          "gas": "0xb3",
   117          "gasUsed": "0x7a",
   118          "input": "0xc605f76c",
   119          "output": "0x"
   120  }`)),
   121  		},
   122  		{
   123  			name: "create2_test",
   124  			fields: fields{
   125  				Type:    CREATE2.String(),
   126  				From:    genAddressPtr("0xe213d8b68ca3d01e51a6dba669de59ac9a8359ee"),
   127  				To:      genAddressPtr("0xd3204138864ad97dbfe703cf7281f6b3397c6003"),
   128  				Value:   "0x0",
   129  				Gas:     11341,
   130  				GasUsed: 10784,
   131  				Input:   "0x6080604052348015600f57600080fd5b50604051602080608183398101806040526020811015602d57600080fd5b810190808051906020019092919050505050603580604c6000396000f3fe6080604052600080fdfea165627a7a72305820c577c5325e4c667e8439f998d616e74110a14fb5b185afe46d8443bbfd9c3d710029",
   132  				Output:  "0x6080604052600080fdfea165627a7a72305820c577c5325e4c667e8439f998d616e74110a14fb5b185afe46d8443bbfd9c3d710029",
   133  			},
   134  			want: jsonMustCompact([]byte(`{
   135  		"type": "CREATE2",
   136          "from": "0xe213d8b68ca3d01e51a6dba669de59ac9a8359ee",
   137  		"to": "0xd3204138864ad97dbfe703cf7281f6b3397c6003",
   138  		"value": "0x0",
   139          "gas": "0x2c4d",
   140          "gasUsed": "0x2a20",
   141          "input": "0x6080604052348015600f57600080fd5b50604051602080608183398101806040526020811015602d57600080fd5b810190808051906020019092919050505050603580604c6000396000f3fe6080604052600080fdfea165627a7a72305820c577c5325e4c667e8439f998d616e74110a14fb5b185afe46d8443bbfd9c3d710029",
   142          "output": "0x6080604052600080fdfea165627a7a72305820c577c5325e4c667e8439f998d616e74110a14fb5b185afe46d8443bbfd9c3d710029"
   143  }`)),
   144  		},
   145  		{
   146  			name: "create_test",
   147  			fields: fields{
   148  				Type:    CREATE.String(),
   149  				From:    genAddressPtr("0x13e4acefe6a6700604929946e70e6443e4e73447"),
   150  				To:      genAddressPtr("0x7dc9c9730689ff0b0fd506c67db815f12d90a448"),
   151  				Value:   "0x0",
   152  				Gas:     385286,
   153  				GasUsed: 385286,
   154  				Input:   "0x6080604052348015600f57600080fd5b50604051602080608183398101806040526020811015602d57600080fd5b810190808051906020019092919050505050603580604c6000396000f3fe6080604052600080fdfea165627a7a72305820c577c5325e4c667e8439f998d616e74110a14fb5b185afe46d8443bbfd9c3d710029",
   155  				Output:  "0x6080604052600080fdfea165627a7a72305820c577c5325e4c667e8439f998d616e74110a14fb5b185afe46d8443bbfd9c3d710029",
   156  			},
   157  			want: jsonMustCompact([]byte(`{
   158      "type": "CREATE",
   159      "from": "0x13e4acefe6a6700604929946e70e6443e4e73447",
   160  	"to": "0x7dc9c9730689ff0b0fd506c67db815f12d90a448",
   161  	"value": "0x0",
   162      "gas": "0x5e106",
   163      "gasUsed": "0x5e106",
   164      "input": "0x6080604052348015600f57600080fd5b50604051602080608183398101806040526020811015602d57600080fd5b810190808051906020019092919050505050603580604c6000396000f3fe6080604052600080fdfea165627a7a72305820c577c5325e4c667e8439f998d616e74110a14fb5b185afe46d8443bbfd9c3d710029",
   165      "output": "0x6080604052600080fdfea165627a7a72305820c577c5325e4c667e8439f998d616e74110a14fb5b185afe46d8443bbfd9c3d710029"
   166  }`)),
   167  		},
   168  		{
   169  			name: "call_test",
   170  			fields: fields{
   171  				Type:    CALL.String(),
   172  				From:    genAddressPtr("0x3693da93b9d5e63cb4804b8813c8214a76724485"),
   173  				To:      genAddressPtr("0x13cf0d18bcb898efd4e85ae2bb65a443ab86023c"),
   174  				Value:   "0x0",
   175  				Gas:     179,
   176  				GasUsed: 122,
   177  				Input:   "0xc605f76c",
   178  				Output:  "0x",
   179  			},
   180  			want: jsonMustCompact([]byte(`{
   181  	"type": "CALL",
   182  	"from": "0x3693da93b9d5e63cb4804b8813c8214a76724485",
   183  	"to": "0x13cf0d18bcb898efd4e85ae2bb65a443ab86023c",
   184  	"value": "0x0",
   185  	"gas": "0xb3",
   186  	"gasUsed": "0x7a",
   187  	"input": "0xc605f76c",
   188  	"output": "0x"
   189  }`)),
   190  		},
   191  		{
   192  			name: "simple_call_test",
   193  			fields: fields{
   194  				Type:  CALL.String(),
   195  				From:  genAddressPtr("0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe"),
   196  				To:    genAddressPtr("0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5"),
   197  				Value: "0x6f05b59d3b20000",
   198  				Input: "0x",
   199  			},
   200  			want: jsonMustCompact([]byte(`{
   201  		"type": "CALL",
   202          "from": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe",
   203  		"to": "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5",
   204  		"value": "0x6f05b59d3b20000",
   205          "input": "0x"
   206  }`)),
   207  		},
   208  		{
   209  			name: "staticcall_test",
   210  			fields: fields{
   211  				Type:    OpCode(STATICCALL).String(),
   212  				From:    genAddressPtr("0xbadc777c579b497ede07fa6ff93bdf4e31793f24"),
   213  				To:      genAddressPtr("0x920fd5070602feaea2e251e9e7238b6c376bcae5"),
   214  				Gas:     179,
   215  				GasUsed: 122,
   216  				Input:   "0xc605f76c",
   217  				Output:  "0x",
   218  			},
   219  			want: jsonMustCompact([]byte(`{
   220  		"type": "STATICCALL",
   221          "from": "0xbadc777c579b497ede07fa6ff93bdf4e31793f24",
   222  		"to": "0x920fd5070602feaea2e251e9e7238b6c376bcae5",
   223          "gas": "0xb3",
   224          "gasUsed": "0x7a",
   225          "input": "0xc605f76c",
   226          "output": "0x"
   227  }`)),
   228  		},
   229  		{
   230  			name: "selfdestruct_test",
   231  			fields: fields{
   232  				Type: OpCode(SELFDESTRUCT).String(),
   233  			},
   234  			want: []byte(`{"type":"SELFDESTRUCT"}`),
   235  		},
   236  	}
   237  	for _, tt := range tests {
   238  		t.Run(tt.name, func(t *testing.T) {
   239  			i := InternalTxTrace{
   240  				Type:     tt.fields.Type,
   241  				From:     tt.fields.From,
   242  				To:       tt.fields.To,
   243  				Value:    tt.fields.Value,
   244  				Gas:      tt.fields.Gas,
   245  				GasUsed:  tt.fields.GasUsed,
   246  				Input:    tt.fields.Input,
   247  				Output:   tt.fields.Output,
   248  				Error:    tt.fields.Error,
   249  				Time:     tt.fields.Time,
   250  				Calls:    tt.fields.Calls,
   251  				Reverted: tt.fields.Reverted,
   252  			}
   253  			got, err := i.MarshalJSON()
   254  			assert.Nil(t, err)
   255  			if !reflect.DeepEqual(got, tt.want) {
   256  				t.Errorf("MarshalJSON() got = %v, want %v", string(got), string(tt.want))
   257  			}
   258  		})
   259  	}
   260  }
   261  
   262  func TestInternalTxTracer_result_invalidOutput(t *testing.T) {
   263  	tracer := NewInternalTxTracer()
   264  	tracer.ctx["error"] = errEvmExecutionReverted
   265  	// An 8 bytes value that might cause a string version error or out-of-range error.
   266  	tracer.ctx["output"] = "0x08c379a0000000000000000000000000000000000000000000000000ffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff"
   267  
   268  	_, err := tracer.GetResult()
   269  	if err != nil {
   270  		t.Fatal(err)
   271  	}
   272  }