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  }