@@ -295,15 +295,15 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
295
295
} else {
296
296
// Initialise a new contract and set the code that is to be used by the EVM.
297
297
// The contract is a scoped environment for this execution context only.
298
- code := evm .StateDB . GetCode (addr )
298
+ code := evm .resolveCode (addr )
299
299
if len (code ) == 0 {
300
300
ret , err = nil , nil // gas is unchanged
301
301
} else {
302
302
addrCopy := addr
303
303
// If the account has no code, we can abort here
304
304
// The depth-check is already done, and precompiles handled above
305
305
contract := NewContract (caller , AccountRef (addrCopy ), value , gas )
306
- contract .SetCallCode (& addrCopy , evm .StateDB . GetCodeHash (addrCopy ), code )
306
+ contract .SetCallCode (& addrCopy , evm .resolveCodeHash (addrCopy ), code )
307
307
ret , err = evm .interpreter .Run (contract , input , false )
308
308
gas = contract .Gas
309
309
}
@@ -363,7 +363,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
363
363
// Initialise a new contract and set the code that is to be used by the EVM.
364
364
// The contract is a scoped environment for this execution context only.
365
365
contract := NewContract (caller , AccountRef (caller .Address ()), value , gas )
366
- contract .SetCallCode (& addrCopy , evm .StateDB . GetCodeHash (addrCopy ), evm .StateDB . GetCode (addrCopy ))
366
+ contract .SetCallCode (& addrCopy , evm .resolveCodeHash (addrCopy ), evm .resolveCode (addrCopy ))
367
367
ret , err = evm .interpreter .Run (contract , input , false )
368
368
gas = contract .Gas
369
369
}
@@ -421,7 +421,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
421
421
addrCopy := addr
422
422
// Initialise a new contract and make initialise the delegate values
423
423
contract := NewContract (caller , AccountRef (caller .Address ()), nil , gas ).AsDelegate ()
424
- contract .SetCallCode (& addrCopy , evm .StateDB . GetCodeHash (addrCopy ), evm .StateDB . GetCode (addrCopy ))
424
+ contract .SetCallCode (& addrCopy , evm .resolveCodeHash (addrCopy ), evm .resolveCode (addrCopy ))
425
425
ret , err = evm .interpreter .Run (contract , input , false )
426
426
gas = contract .Gas
427
427
}
@@ -477,7 +477,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
477
477
// Initialise a new contract and set the code that is to be used by the EVM.
478
478
// The contract is a scoped environment for this execution context only.
479
479
contract := NewContract (caller , AccountRef (addrCopy ), new (big.Int ), gas )
480
- contract .SetCallCode (& addrCopy , evm .StateDB . GetCodeHash (addrCopy ), evm .StateDB . GetCode (addrCopy ))
480
+ contract .SetCallCode (& addrCopy , evm .resolveCodeHash (addrCopy ), evm .resolveCode (addrCopy ))
481
481
// When an error was returned by the EVM or when setting the creation code
482
482
// above we revert to the snapshot and consume any gas remaining. Additionally
483
483
// when we're in Homestead this also counts for code storage gas errors.
@@ -666,17 +666,46 @@ func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *
666
666
return evm .create (caller , codeAndHash , gas , endowment , contractAddr , CREATE2 )
667
667
}
668
668
669
+ // resolveCode returns the code associated with the provided account. After
670
+ // Prague, it can also resolve code pointed to by a delegation designator.
671
+ func (evm * EVM ) resolveCode (addr common.Address ) []byte {
672
+ code := evm .StateDB .GetCode (addr )
673
+ if ! evm .chainRules .IsPrague {
674
+ return code
675
+ }
676
+ if target , ok := types .ParseDelegation (code ); ok {
677
+ // Note we only follow one level of delegation.
678
+ return evm .StateDB .GetCode (target )
679
+ }
680
+ return code
681
+ }
682
+
683
+ // resolveCodeHash returns the code hash associated with the provided address.
684
+ // After Prague, it can also resolve code hash of the account pointed to by a
685
+ // delegation designator. Although this is not accessible in the EVM it is used
686
+ // internally to associate jumpdest analysis to code.
687
+ func (evm * EVM ) resolveCodeHash (addr common.Address ) common.Hash {
688
+ if evm .chainRules .IsPrague {
689
+ code := evm .StateDB .GetCode (addr )
690
+ if target , ok := types .ParseDelegation (code ); ok {
691
+ // Note we only follow one level of delegation.
692
+ return evm .StateDB .GetCodeHash (target )
693
+ }
694
+ }
695
+ return evm .StateDB .GetCodeHash (addr )
696
+ }
697
+
669
698
// ChainConfig returns the environment's chain configuration
670
699
func (evm * EVM ) ChainConfig () * params.ChainConfig { return evm .chainConfig }
671
700
672
701
// PublishEvent executes Publish function from OpEvent if OpCode is found in Context.PublishEvents
673
702
func (evm * EVM ) PublishEvent (
674
- opCode OpCode ,
675
- counter uint64 ,
676
- from , to common.Address ,
677
- value * big.Int ,
678
- input , output []byte ,
679
- err error ,
703
+ opCode OpCode ,
704
+ counter uint64 ,
705
+ from , to common.Address ,
706
+ value * big.Int ,
707
+ input , output []byte ,
708
+ err error ,
680
709
) {
681
710
context := evm .Context
682
711
if context .CurrentTransaction == nil {
0 commit comments