Run loops and evaluates the contract's code with the given input data and returns the return byte-slice and an error if one occurred. It's important to note that any errors returned by the interpreter should be considered a revert-and-consume-all-gas operation except for errExecutionReverted which
(contract *Contract, input []byte)
| 92 | // considered a revert-and-consume-all-gas operation except for |
| 93 | // errExecutionReverted which means revert-and-keep-gas-left. |
| 94 | func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err error) { |
| 95 | if in.intPool == nil { |
| 96 | in.intPool = poolOfIntPools.get() |
| 97 | defer func() { |
| 98 | poolOfIntPools.put(in.intPool) |
| 99 | in.intPool = nil |
| 100 | }() |
| 101 | } |
| 102 | |
| 103 | // Increment the call depth which is restricted to 1024 |
| 104 | in.evm.depth++ |
| 105 | defer func() { in.evm.depth-- }() |
| 106 | |
| 107 | // Reset the previous call's return data. It's unimportant to preserve the old buffer |
| 108 | // as every returning call will return new data anyway. |
| 109 | in.returnData = nil |
| 110 | |
| 111 | // Don't bother with the execution if there's no code. |
| 112 | if len(contract.Code) == 0 { |
| 113 | return nil, nil |
| 114 | } |
| 115 | |
| 116 | var ( |
| 117 | op OpCode // current opcode |
| 118 | mem = NewMemory() // bound memory |
| 119 | stack = newstack() // local stack |
| 120 | // For optimisation reason we're using uint64 as the program counter. |
| 121 | // It's theoretically possible to go above 2^64. The YP defines the PC |
| 122 | // to be uint256. Practically much less so feasible. |
| 123 | pc = uint64(0) // program counter |
| 124 | cost uint64 |
| 125 | // copies used by tracer |
| 126 | pcCopy uint64 // needed for the deferred Tracer |
| 127 | gasCopy uint64 // for Tracer to log gas remaining before execution |
| 128 | logged bool // deferred Tracer should ignore already logged steps |
| 129 | ) |
| 130 | contract.Input = input |
| 131 | |
| 132 | // Reclaim the stack as an int pool when the execution stops |
| 133 | defer func() { in.intPool.put(stack.data...) }() |
| 134 | |
| 135 | if in.cfg.Debug { |
| 136 | defer func() { |
| 137 | if err != nil { |
| 138 | if !logged { |
| 139 | in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) |
| 140 | } else { |
| 141 | in.cfg.Tracer.CaptureFault(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) |
| 142 | } |
| 143 | } |
| 144 | }() |
| 145 | } |
| 146 | // The Interpreter main run loop (contextual). This loop runs until either an |
| 147 | // explicit STOP, RETURN or SELFDESTRUCT is executed, an error occurred during |
| 148 | // the execution of one of the operations or until the done flag is set by the |
| 149 | // parent context. |
| 150 | for atomic.LoadInt32(&in.evm.abort) == 0 { |
| 151 | if in.cfg.Debug { |
nothing calls this directly
no test coverage detected