@@ -95,15 +95,10 @@ type EVM struct {
95
95
// activePrecompiles defines the precompiles that are currently active
96
96
activePrecompiles []common.Address
97
97
98
- // preExecuteCallback is a callback function that is called before executing
99
- // CALL, CALLCODE, DELEGATECALL and STATICCALL opcodes.
100
- preExecuteCallback preExecuteCallbackType
101
- }
102
-
103
- type preExecuteCallbackType func (evm * EVM , addr common.Address ) error
104
-
105
- func dummyCallback (evm * EVM , addr common.Address ) error {
106
- return nil
98
+ // hooks is a set of functions that can be used to intercept and modify the
99
+ // behavior of the EVM when executing certain opcodes.
100
+ // The hooks are called before the execution of the respective opcodes.
101
+ hooks OpCodeHooks
107
102
}
108
103
109
104
// NewEVM returns a new EVM. The returned EVM is not thread safe and should
@@ -121,13 +116,13 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig
121
116
}
122
117
}
123
118
evm := & EVM {
124
- Context : blockCtx ,
125
- TxContext : txCtx ,
126
- StateDB : statedb ,
127
- Config : config ,
128
- chainConfig : chainConfig ,
129
- chainRules : chainConfig .Rules (blockCtx .BlockNumber , blockCtx .Random != nil , blockCtx .Time ),
130
- preExecuteCallback : dummyCallback ,
119
+ Context : blockCtx ,
120
+ TxContext : txCtx ,
121
+ StateDB : statedb ,
122
+ Config : config ,
123
+ chainConfig : chainConfig ,
124
+ chainRules : chainConfig .Rules (blockCtx .BlockNumber , blockCtx .Random != nil , blockCtx .Time ),
125
+ hooks : newNoopOpCodeHooks () ,
131
126
}
132
127
// set the default precompiles
133
128
evm .activePrecompiles = DefaultActivePrecompiles (evm .chainRules )
@@ -137,17 +132,17 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig
137
132
return evm
138
133
}
139
134
140
- // NewEVMWithCallback returns a new EVM and takes a custom preExecuteCallback . The returned EVM is
135
+ // NewEVMWithHooks returns a new EVM and takes a custom OpCodeHooks . The returned EVM is
141
136
// not thread safe and should only ever be used *once*.
142
- func NewEVMWithCallback ( callback preExecuteCallbackType , blockCtx BlockContext , txCtx TxContext , statedb StateDB , chainConfig * params.ChainConfig , config Config ) * EVM {
137
+ func NewEVMWithHooks ( hooks OpCodeHooks , blockCtx BlockContext , txCtx TxContext , statedb StateDB , chainConfig * params.ChainConfig , config Config ) * EVM {
143
138
evm := & EVM {
144
- Context : blockCtx ,
145
- TxContext : txCtx ,
146
- StateDB : statedb ,
147
- Config : config ,
148
- chainConfig : chainConfig ,
149
- chainRules : chainConfig .Rules (blockCtx .BlockNumber , blockCtx .Random != nil , blockCtx .Time ),
150
- preExecuteCallback : callback ,
139
+ Context : blockCtx ,
140
+ TxContext : txCtx ,
141
+ StateDB : statedb ,
142
+ Config : config ,
143
+ chainConfig : chainConfig ,
144
+ chainRules : chainConfig .Rules (blockCtx .BlockNumber , blockCtx .Random != nil , blockCtx .Time ),
145
+ hooks : hooks ,
151
146
}
152
147
// set the default precompiles
153
148
evm .activePrecompiles = DefaultActivePrecompiles (evm .chainRules )
@@ -190,8 +185,7 @@ func (evm *EVM) WithInterpreter(interpreter Interpreter) {
190
185
// the necessary steps to create accounts and reverses the state in case of an
191
186
// execution error or failed value transfer.
192
187
func (evm * EVM ) Call (caller ContractRef , addr common.Address , input []byte , gas uint64 , value * uint256.Int ) (ret []byte , leftOverGas uint64 , err error ) {
193
- err = evm .preExecuteCallback (evm , addr )
194
- if err != nil {
188
+ if err = evm .hooks .CallHook (evm , caller .Address (), addr ); err != nil {
195
189
return nil , gas , err
196
190
}
197
191
@@ -284,8 +278,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
284
278
// CallCode differs from Call in the sense that it executes the given address'
285
279
// code with the caller as context.
286
280
func (evm * EVM ) CallCode (caller ContractRef , addr common.Address , input []byte , gas uint64 , value * uint256.Int ) (ret []byte , leftOverGas uint64 , err error ) {
287
- err = evm .preExecuteCallback (evm , addr )
288
- if err != nil {
281
+ if err = evm .hooks .CallHook (evm , caller .Address (), addr ); err != nil {
289
282
return nil , gas , err
290
283
}
291
284
@@ -337,8 +330,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
337
330
// DelegateCall differs from CallCode in the sense that it executes the given address'
338
331
// code with the caller as context and the caller is set to the caller of the caller.
339
332
func (evm * EVM ) DelegateCall (caller ContractRef , addr common.Address , input []byte , gas uint64 ) (ret []byte , leftOverGas uint64 , err error ) {
340
- err = evm .preExecuteCallback (evm , addr )
341
- if err != nil {
333
+ if err = evm .hooks .CallHook (evm , caller .Address (), addr ); err != nil {
342
334
return nil , gas , err
343
335
}
344
336
@@ -385,8 +377,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
385
377
// Opcodes that attempt to perform such modifications will result in exceptions
386
378
// instead of performing the modifications.
387
379
func (evm * EVM ) StaticCall (caller ContractRef , addr common.Address , input []byte , gas uint64 ) (ret []byte , leftOverGas uint64 , err error ) {
388
- err = evm .preExecuteCallback (evm , addr )
389
- if err != nil {
380
+ if err = evm .hooks .CallHook (evm , caller .Address (), addr ); err != nil {
390
381
return nil , gas , err
391
382
}
392
383
@@ -547,6 +538,9 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
547
538
548
539
// Create creates a new contract using code as deployment code.
549
540
func (evm * EVM ) Create (caller ContractRef , code []byte , gas uint64 , value * uint256.Int ) (ret []byte , contractAddr common.Address , leftOverGas uint64 , err error ) {
541
+ if err = evm .hooks .CreateHook (evm , caller .Address ()); err != nil {
542
+ return nil , common.Address {}, gas , err
543
+ }
550
544
contractAddr = crypto .CreateAddress (caller .Address (), evm .StateDB .GetNonce (caller .Address ()))
551
545
return evm .create (caller , & codeAndHash {code : code }, gas , value , contractAddr , CREATE )
552
546
}
@@ -556,6 +550,9 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *uint2
556
550
// The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:]
557
551
// instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
558
552
func (evm * EVM ) Create2 (caller ContractRef , code []byte , gas uint64 , endowment * uint256.Int , salt * uint256.Int ) (ret []byte , contractAddr common.Address , leftOverGas uint64 , err error ) {
553
+ if err = evm .hooks .CreateHook (evm , caller .Address ()); err != nil {
554
+ return nil , common.Address {}, gas , err
555
+ }
559
556
codeAndHash := & codeAndHash {code : code }
560
557
contractAddr = crypto .CreateAddress2 (caller .Address (), salt .Bytes32 (), codeAndHash .Hash ().Bytes ())
561
558
return evm .create (caller , codeAndHash , gas , endowment , contractAddr , CREATE2 )
0 commit comments