github.com/klaytn/klaytn@v1.12.1/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 "errors" 30 "reflect" 31 "testing" 32 "time" 33 34 "github.com/stretchr/testify/assert" 35 36 "github.com/klaytn/klaytn/common" 37 ) 38 39 func jsonMustCompact(data []byte) []byte { 40 compactedBuffer := new(bytes.Buffer) 41 err := json.Compact(compactedBuffer, data) 42 if err != nil { 43 panic(err) 44 } 45 return compactedBuffer.Bytes() 46 } 47 48 func genAddressPtr(addr string) *common.Address { 49 ret := common.HexToAddress(addr) 50 return &ret 51 } 52 53 func TestInternalTxTrace_MarshalJSON(t *testing.T) { 54 type fields struct { 55 Type string 56 From *common.Address 57 To *common.Address 58 Value string 59 Gas uint64 60 GasUsed uint64 61 Input string 62 Output string 63 Error error 64 Time time.Duration 65 Calls []*InternalTxTrace 66 Reverted *RevertedInfo 67 } 68 tests := []struct { 69 name string 70 fields fields 71 want []byte 72 }{ 73 { 74 name: "revert_test", 75 fields: fields{ 76 Type: CALL.String(), 77 From: genAddressPtr("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), 78 To: genAddressPtr("0xabbcd5b340c80b5f1c0545c04c987b87310296ae"), 79 Value: "0x0", 80 Gas: 2971112, 81 GasUsed: 195, 82 Input: "0x73b40a5c000000000000000000000000400de2e016bda6577407dfc379faba9899bc73ef0000000000000000000000002cc31912b2b0f3075a87b3640923d45a26cef3ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d79d8e6c7265636f76657279416464726573730000000000000000000000000000000000000000000000000000000000383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988383e3ec32dc0f66d8fe60dbdc2f6815bdf73a98800000000000000000000000000000000000000000000000000000000000000000000000000000000", 83 Error: errExecutionReverted, 84 Reverted: &RevertedInfo{ 85 Contract: genAddressPtr("0xabbcd5b340c80b5f1c0545c04c987b87310296ae"), 86 }, 87 }, 88 want: jsonMustCompact([]byte(`{ 89 "type": "CALL", 90 "from": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", 91 "to": "0xabbcd5b340c80b5f1c0545c04c987b87310296ae", 92 "value": "0x0", 93 "gas": "0x2d55e8", 94 "gasUsed": "0xc3", 95 "input": "0x73b40a5c000000000000000000000000400de2e016bda6577407dfc379faba9899bc73ef0000000000000000000000002cc31912b2b0f3075a87b3640923d45a26cef3ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d79d8e6c7265636f76657279416464726573730000000000000000000000000000000000000000000000000000000000383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988383e3ec32dc0f66d8fe60dbdc2f6815bdf73a98800000000000000000000000000000000000000000000000000000000000000000000000000000000", 96 "error": "execution reverted", 97 "reverted": { 98 "contract": "0xabbcd5b340c80b5f1c0545c04c987b87310296ae" 99 } 100 }`)), 101 }, 102 { 103 name: "delegatecall_test", 104 fields: fields{ 105 Type: DELEGATECALL.String(), 106 From: genAddressPtr("0x2074f91470365144df78c333948814fe4158af5a"), 107 To: genAddressPtr("0x13cf0d18bcb898efd4e85ae2bb65a443ab86023c"), 108 Gas: 179, 109 GasUsed: 122, 110 Input: "0xc605f76c", 111 Output: "0x", 112 }, 113 want: jsonMustCompact([]byte(`{ 114 "type": "DELEGATECALL", 115 "from": "0x2074f91470365144df78c333948814fe4158af5a", 116 "to": "0x13cf0d18bcb898efd4e85ae2bb65a443ab86023c", 117 "gas": "0xb3", 118 "gasUsed": "0x7a", 119 "input": "0xc605f76c", 120 "output": "0x" 121 }`)), 122 }, 123 { 124 name: "create2_test", 125 fields: fields{ 126 Type: CREATE2.String(), 127 From: genAddressPtr("0xe213d8b68ca3d01e51a6dba669de59ac9a8359ee"), 128 To: genAddressPtr("0xd3204138864ad97dbfe703cf7281f6b3397c6003"), 129 Value: "0x0", 130 Gas: 11341, 131 GasUsed: 10784, 132 Input: "0x6080604052348015600f57600080fd5b50604051602080608183398101806040526020811015602d57600080fd5b810190808051906020019092919050505050603580604c6000396000f3fe6080604052600080fdfea165627a7a72305820c577c5325e4c667e8439f998d616e74110a14fb5b185afe46d8443bbfd9c3d710029", 133 Output: "0x6080604052600080fdfea165627a7a72305820c577c5325e4c667e8439f998d616e74110a14fb5b185afe46d8443bbfd9c3d710029", 134 }, 135 want: jsonMustCompact([]byte(`{ 136 "type": "CREATE2", 137 "from": "0xe213d8b68ca3d01e51a6dba669de59ac9a8359ee", 138 "to": "0xd3204138864ad97dbfe703cf7281f6b3397c6003", 139 "value": "0x0", 140 "gas": "0x2c4d", 141 "gasUsed": "0x2a20", 142 "input": "0x6080604052348015600f57600080fd5b50604051602080608183398101806040526020811015602d57600080fd5b810190808051906020019092919050505050603580604c6000396000f3fe6080604052600080fdfea165627a7a72305820c577c5325e4c667e8439f998d616e74110a14fb5b185afe46d8443bbfd9c3d710029", 143 "output": "0x6080604052600080fdfea165627a7a72305820c577c5325e4c667e8439f998d616e74110a14fb5b185afe46d8443bbfd9c3d710029" 144 }`)), 145 }, 146 { 147 name: "create_test", 148 fields: fields{ 149 Type: CREATE.String(), 150 From: genAddressPtr("0x13e4acefe6a6700604929946e70e6443e4e73447"), 151 To: genAddressPtr("0x7dc9c9730689ff0b0fd506c67db815f12d90a448"), 152 Value: "0x0", 153 Gas: 385286, 154 GasUsed: 385286, 155 Input: "0x6080604052348015600f57600080fd5b50604051602080608183398101806040526020811015602d57600080fd5b810190808051906020019092919050505050603580604c6000396000f3fe6080604052600080fdfea165627a7a72305820c577c5325e4c667e8439f998d616e74110a14fb5b185afe46d8443bbfd9c3d710029", 156 Output: "0x6080604052600080fdfea165627a7a72305820c577c5325e4c667e8439f998d616e74110a14fb5b185afe46d8443bbfd9c3d710029", 157 }, 158 want: jsonMustCompact([]byte(`{ 159 "type": "CREATE", 160 "from": "0x13e4acefe6a6700604929946e70e6443e4e73447", 161 "to": "0x7dc9c9730689ff0b0fd506c67db815f12d90a448", 162 "value": "0x0", 163 "gas": "0x5e106", 164 "gasUsed": "0x5e106", 165 "input": "0x6080604052348015600f57600080fd5b50604051602080608183398101806040526020811015602d57600080fd5b810190808051906020019092919050505050603580604c6000396000f3fe6080604052600080fdfea165627a7a72305820c577c5325e4c667e8439f998d616e74110a14fb5b185afe46d8443bbfd9c3d710029", 166 "output": "0x6080604052600080fdfea165627a7a72305820c577c5325e4c667e8439f998d616e74110a14fb5b185afe46d8443bbfd9c3d710029" 167 }`)), 168 }, 169 { 170 name: "call_test", 171 fields: fields{ 172 Type: CALL.String(), 173 From: genAddressPtr("0x3693da93b9d5e63cb4804b8813c8214a76724485"), 174 To: genAddressPtr("0x13cf0d18bcb898efd4e85ae2bb65a443ab86023c"), 175 Value: "0x0", 176 Gas: 179, 177 GasUsed: 122, 178 Input: "0xc605f76c", 179 Output: "0x", 180 }, 181 want: jsonMustCompact([]byte(`{ 182 "type": "CALL", 183 "from": "0x3693da93b9d5e63cb4804b8813c8214a76724485", 184 "to": "0x13cf0d18bcb898efd4e85ae2bb65a443ab86023c", 185 "value": "0x0", 186 "gas": "0xb3", 187 "gasUsed": "0x7a", 188 "input": "0xc605f76c", 189 "output": "0x" 190 }`)), 191 }, 192 { 193 name: "simple_call_test", 194 fields: fields{ 195 Type: CALL.String(), 196 From: genAddressPtr("0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe"), 197 To: genAddressPtr("0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5"), 198 Value: "0x6f05b59d3b20000", 199 Input: "0x", 200 }, 201 want: jsonMustCompact([]byte(`{ 202 "type": "CALL", 203 "from": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe", 204 "to": "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5", 205 "value": "0x6f05b59d3b20000", 206 "input": "0x" 207 }`)), 208 }, 209 { 210 name: "staticcall_test", 211 fields: fields{ 212 Type: OpCode(STATICCALL).String(), 213 From: genAddressPtr("0xbadc777c579b497ede07fa6ff93bdf4e31793f24"), 214 To: genAddressPtr("0x920fd5070602feaea2e251e9e7238b6c376bcae5"), 215 Gas: 179, 216 GasUsed: 122, 217 Input: "0xc605f76c", 218 Output: "0x", 219 }, 220 want: jsonMustCompact([]byte(`{ 221 "type": "STATICCALL", 222 "from": "0xbadc777c579b497ede07fa6ff93bdf4e31793f24", 223 "to": "0x920fd5070602feaea2e251e9e7238b6c376bcae5", 224 "gas": "0xb3", 225 "gasUsed": "0x7a", 226 "input": "0xc605f76c", 227 "output": "0x" 228 }`)), 229 }, 230 { 231 name: "selfdestruct_test", 232 fields: fields{ 233 Type: OpCode(SELFDESTRUCT).String(), 234 }, 235 want: []byte(`{"type":"SELFDESTRUCT"}`), 236 }, 237 } 238 for _, tt := range tests { 239 t.Run(tt.name, func(t *testing.T) { 240 i := InternalTxTrace{ 241 Type: tt.fields.Type, 242 From: tt.fields.From, 243 To: tt.fields.To, 244 Value: tt.fields.Value, 245 Gas: tt.fields.Gas, 246 GasUsed: tt.fields.GasUsed, 247 Input: tt.fields.Input, 248 Output: tt.fields.Output, 249 Error: tt.fields.Error, 250 Time: tt.fields.Time, 251 Calls: tt.fields.Calls, 252 Reverted: tt.fields.Reverted, 253 } 254 got, err := i.MarshalJSON() 255 assert.Nil(t, err) 256 if !reflect.DeepEqual(got, tt.want) { 257 t.Errorf("MarshalJSON() got = %v, want %v", string(got), string(tt.want)) 258 } 259 }) 260 } 261 } 262 263 func TestInternalTxTracer_result_invalidOutput(t *testing.T) { 264 tracer := NewInternalTxTracer() 265 tracer.ctx["error"] = errors.New("evm: execution reverted") 266 // An 8 bytes value that might cause a string version error or out-of-range error. 267 tracer.ctx["output"] = "0x08c379a0000000000000000000000000000000000000000000000000ffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff" 268 269 _, err := tracer.GetResult() 270 if err != nil { 271 t.Fatal(err) 272 } 273 }