github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/types/api.go (about) 1 package types 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "math/big" 7 8 "github.com/ethereum/go-ethereum/common" 9 "github.com/ethereum/go-ethereum/common/hexutil" 10 "github.com/ethereum/go-ethereum/core/vm" 11 ) 12 13 // TraceExecutionResult groups all structured logs emitted by the EVM 14 // while replaying a transaction in debug mode as well as transaction 15 // execution status, the amount of gas used and the return value 16 type TraceExecutionResult struct { 17 Gas uint64 `json:"gas"` 18 Failed bool `json:"failed"` 19 ReturnValue string `json:"returnValue"` 20 StructLogs []*StructLogRes `json:"structLogs"` 21 } 22 23 // StructLogRes stores a structured log emitted by the EVM while replaying a 24 // transaction in debug mode 25 type StructLogRes struct { 26 Pc uint64 `json:"pc"` 27 Op string `json:"op"` 28 Gas uint64 `json:"gas"` 29 GasCost uint64 `json:"gasCost"` 30 Depth int `json:"depth"` 31 Error error `json:"error,omitempty"` 32 Stack *[]string `json:"stack,omitempty"` 33 Memory *[]string `json:"memory,omitempty"` 34 Storage *map[string]string `json:"storage,omitempty"` 35 } 36 37 // FormatLogs formats EVM returned structured logs for json output 38 func FormatLogs(logs []vm.StructLog) []*StructLogRes { 39 formatted := make([]*StructLogRes, len(logs)) 40 for index, trace := range logs { 41 formatted[index] = &StructLogRes{ 42 Pc: trace.Pc, 43 Op: trace.Op.String(), 44 Gas: trace.Gas, 45 GasCost: trace.GasCost, 46 Depth: trace.Depth, 47 Error: trace.Err, 48 } 49 if trace.Stack != nil { 50 stack := make([]string, len(trace.Stack)) 51 for i, stackValue := range trace.Stack { 52 stack[i] = stackValue.Hex() 53 } 54 formatted[index].Stack = &stack 55 } 56 if trace.Memory != nil { 57 memory := make([]string, 0, (len(trace.Memory)+31)/32) 58 for i := 0; i+32 <= len(trace.Memory); i += 32 { 59 memory = append(memory, fmt.Sprintf("%x", trace.Memory[i:i+32])) 60 } 61 formatted[index].Memory = &memory 62 } 63 if trace.Storage != nil { 64 storage := make(map[string]string) 65 for i, storageValue := range trace.Storage { 66 storage[fmt.Sprintf("%x", i)] = fmt.Sprintf("%x", storageValue) 67 } 68 formatted[index].Storage = &storage 69 } 70 } 71 return formatted 72 } 73 74 // Account indicates the overriding fields of account during the execution of 75 // a message call. 76 // NOTE: state and stateDiff can't be specified at the same time. If state is 77 // set, message execution will only use the data in the given state. Otherwise 78 // if statDiff is set, all diff will be applied first and then execute the call 79 // message. 80 type OverrideAccount struct { 81 Nonce *hexutil.Uint64 `json:"nonce"` 82 Code *hexutil.Bytes `json:"code"` 83 Balance **hexutil.Big `json:"balance"` 84 State *map[common.Hash]common.Hash `json:"state"` 85 StateDiff *map[common.Hash]common.Hash `json:"stateDiff"` 86 } 87 88 // StateOverride is the collection of overridden accounts. 89 type StateOverrides map[common.Address]OverrideAccount 90 91 // Apply overrides the fields of specified accounts into the given state. 92 func (diff *StateOverrides) Apply(state *CommitStateDB) { 93 for addr, account := range *diff { 94 // Override account nonce. 95 if account.Nonce != nil { 96 state.SetNonce(addr, uint64(*account.Nonce)) 97 } 98 // Override account(contract) code. 99 if account.Code != nil { 100 state.SetCode(addr, *account.Code) 101 } 102 // Override account balance. 103 if account.Balance != nil { 104 state.SetBalance(addr, (*big.Int)(*account.Balance)) 105 } 106 // Replace entire state if caller requires. 107 if account.State != nil { 108 state.SetStorage(addr, *account.State) 109 } 110 // Apply state diff into specified accounts. 111 if account.StateDiff != nil { 112 for key, value := range *account.StateDiff { 113 state.SetState(addr, key, value) 114 } 115 } 116 } 117 } 118 func (diff *StateOverrides) Check() error { 119 for addr, account := range *diff { 120 if account.State != nil && account.StateDiff != nil { 121 return fmt.Errorf("account %s has both 'state' and 'stateDiff'", addr.Hex()) 122 } 123 } 124 return nil 125 } 126 func (diff *StateOverrides) ToString() (string, error) { 127 valStr, err := json.Marshal(diff) 128 return string(valStr), err 129 } 130 func (diff *StateOverrides) GetBytes() ([]byte, error) { 131 return json.Marshal(diff) 132 }