github.com/ethereum/go-ethereum@v1.16.1/core/vm/errors.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package vm 18 19 import ( 20 "errors" 21 "fmt" 22 "math" 23 ) 24 25 // List evm execution errors 26 var ( 27 ErrOutOfGas = errors.New("out of gas") 28 ErrCodeStoreOutOfGas = errors.New("contract creation code storage out of gas") 29 ErrDepth = errors.New("max call depth exceeded") 30 ErrInsufficientBalance = errors.New("insufficient balance for transfer") 31 ErrContractAddressCollision = errors.New("contract address collision") 32 ErrExecutionReverted = errors.New("execution reverted") 33 ErrMaxCodeSizeExceeded = errors.New("max code size exceeded") 34 ErrMaxInitCodeSizeExceeded = errors.New("max initcode size exceeded") 35 ErrInvalidJump = errors.New("invalid jump destination") 36 ErrWriteProtection = errors.New("write protection") 37 ErrReturnDataOutOfBounds = errors.New("return data out of bounds") 38 ErrGasUintOverflow = errors.New("gas uint64 overflow") 39 ErrInvalidCode = errors.New("invalid code: must not begin with 0xef") 40 ErrNonceUintOverflow = errors.New("nonce uint64 overflow") 41 42 // errStopToken is an internal token indicating interpreter loop termination, 43 // never returned to outside callers. 44 errStopToken = errors.New("stop token") 45 ) 46 47 // ErrStackUnderflow wraps an evm error when the items on the stack less 48 // than the minimal requirement. 49 type ErrStackUnderflow struct { 50 stackLen int 51 required int 52 } 53 54 func (e ErrStackUnderflow) Error() string { 55 return fmt.Sprintf("stack underflow (%d <=> %d)", e.stackLen, e.required) 56 } 57 58 func (e ErrStackUnderflow) Unwrap() error { 59 return errors.New("stack underflow") 60 } 61 62 // ErrStackOverflow wraps an evm error when the items on the stack exceeds 63 // the maximum allowance. 64 type ErrStackOverflow struct { 65 stackLen int 66 limit int 67 } 68 69 func (e ErrStackOverflow) Error() string { 70 return fmt.Sprintf("stack limit reached %d (%d)", e.stackLen, e.limit) 71 } 72 73 func (e ErrStackOverflow) Unwrap() error { 74 return errors.New("stack overflow") 75 } 76 77 // ErrInvalidOpCode wraps an evm error when an invalid opcode is encountered. 78 type ErrInvalidOpCode struct { 79 opcode OpCode 80 } 81 82 func (e *ErrInvalidOpCode) Error() string { return fmt.Sprintf("invalid opcode: %s", e.opcode) } 83 84 // rpcError is the same interface as the one defined in rpc/errors.go 85 // but we do not want to depend on rpc package here so we redefine it. 86 // 87 // It's used to ensure that the VMError implements the RPC error interface. 88 type rpcError interface { 89 Error() string // returns the message 90 ErrorCode() int // returns the code 91 } 92 93 var _ rpcError = (*VMError)(nil) 94 95 // VMError wraps a VM error with an additional stable error code. The error 96 // field is the original error that caused the VM error and must be one of the 97 // VM error defined at the top of this file. 98 // 99 // If the error is not one of the known error above, the error code will be 100 // set to VMErrorCodeUnknown. 101 type VMError struct { 102 error 103 code int 104 } 105 106 func VMErrorFromErr(err error) error { 107 if err == nil { 108 return nil 109 } 110 111 return &VMError{ 112 error: err, 113 code: vmErrorCodeFromErr(err), 114 } 115 } 116 117 func (e *VMError) Error() string { 118 return e.error.Error() 119 } 120 121 func (e *VMError) Unwrap() error { 122 return e.error 123 } 124 125 func (e *VMError) ErrorCode() int { 126 return e.code 127 } 128 129 const ( 130 // We start the error code at 1 so that we can use 0 later for some possible extension. There 131 // is no unspecified value for the code today because it should always be set to a valid value 132 // that could be VMErrorCodeUnknown if the error is not mapped to a known error code. 133 134 VMErrorCodeOutOfGas = 1 + iota 135 VMErrorCodeCodeStoreOutOfGas 136 VMErrorCodeDepth 137 VMErrorCodeInsufficientBalance 138 VMErrorCodeContractAddressCollision 139 VMErrorCodeExecutionReverted 140 VMErrorCodeMaxCodeSizeExceeded 141 VMErrorCodeInvalidJump 142 VMErrorCodeWriteProtection 143 VMErrorCodeReturnDataOutOfBounds 144 VMErrorCodeGasUintOverflow 145 VMErrorCodeInvalidCode 146 VMErrorCodeNonceUintOverflow 147 VMErrorCodeStackUnderflow 148 VMErrorCodeStackOverflow 149 VMErrorCodeInvalidOpCode 150 151 // VMErrorCodeUnknown explicitly marks an error as unknown, this is useful when error is converted 152 // from an actual `error` in which case if the mapping is not known, we can use this value to indicate that. 153 VMErrorCodeUnknown = math.MaxInt - 1 154 ) 155 156 func vmErrorCodeFromErr(err error) int { 157 switch { 158 case errors.Is(err, ErrOutOfGas): 159 return VMErrorCodeOutOfGas 160 case errors.Is(err, ErrCodeStoreOutOfGas): 161 return VMErrorCodeCodeStoreOutOfGas 162 case errors.Is(err, ErrDepth): 163 return VMErrorCodeDepth 164 case errors.Is(err, ErrInsufficientBalance): 165 return VMErrorCodeInsufficientBalance 166 case errors.Is(err, ErrContractAddressCollision): 167 return VMErrorCodeContractAddressCollision 168 case errors.Is(err, ErrExecutionReverted): 169 return VMErrorCodeExecutionReverted 170 case errors.Is(err, ErrMaxCodeSizeExceeded): 171 return VMErrorCodeMaxCodeSizeExceeded 172 case errors.Is(err, ErrInvalidJump): 173 return VMErrorCodeInvalidJump 174 case errors.Is(err, ErrWriteProtection): 175 return VMErrorCodeWriteProtection 176 case errors.Is(err, ErrReturnDataOutOfBounds): 177 return VMErrorCodeReturnDataOutOfBounds 178 case errors.Is(err, ErrGasUintOverflow): 179 return VMErrorCodeGasUintOverflow 180 case errors.Is(err, ErrInvalidCode): 181 return VMErrorCodeInvalidCode 182 case errors.Is(err, ErrNonceUintOverflow): 183 return VMErrorCodeNonceUintOverflow 184 185 default: 186 // Dynamic errors 187 if v := (*ErrStackUnderflow)(nil); errors.As(err, &v) { 188 return VMErrorCodeStackUnderflow 189 } 190 191 if v := (*ErrStackOverflow)(nil); errors.As(err, &v) { 192 return VMErrorCodeStackOverflow 193 } 194 195 if v := (*ErrInvalidOpCode)(nil); errors.As(err, &v) { 196 return VMErrorCodeInvalidOpCode 197 } 198 199 return VMErrorCodeUnknown 200 } 201 }