aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm/evm.go
diff options
context:
space:
mode:
authorJeffrey Wilcke <jeffrey@ethereum.org>2017-08-15 16:23:23 +0800
committerPéter Szilágyi <peterke@gmail.com>2017-08-15 18:03:49 +0800
commit3d123bcde67973b57c0a9e7edc219cc2ea589443 (patch)
treee806ab2faae07184fdcdfe23488b7111e75a9057 /core/vm/evm.go
parent9facf6423dbd38ebd7fbd9069cbcb98b0fd243c2 (diff)
downloadgo-tangerine-3d123bcde67973b57c0a9e7edc219cc2ea589443.tar.gz
go-tangerine-3d123bcde67973b57c0a9e7edc219cc2ea589443.tar.zst
go-tangerine-3d123bcde67973b57c0a9e7edc219cc2ea589443.zip
core/vm: implement metropolis static call opcode
Diffstat (limited to 'core/vm/evm.go')
-rw-r--r--core/vm/evm.go45
1 files changed, 45 insertions, 0 deletions
diff --git a/core/vm/evm.go b/core/vm/evm.go
index b8af9bd15..97a9d3105 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -245,6 +245,51 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
return ret, contract.Gas, err
}
+func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
+ if evm.vmConfig.NoRecursion && evm.depth > 0 {
+ return nil, gas, nil
+ }
+
+ // Depth check execution. Fail if we're trying to execute above the
+ // limit.
+ if evm.depth > int(params.CallCreateDepth) {
+ return nil, gas, ErrDepth
+ }
+
+ // make sure the readonly is only set if we aren't in readonly yet
+ // this makes also sure that the readonly flag isn't removed for
+ // child calls.
+ if !evm.interpreter.readonly {
+ evm.interpreter.readonly = true
+ defer func() { evm.interpreter.readonly = false }()
+ }
+
+ var (
+ to = AccountRef(addr)
+ snapshot = evm.StateDB.Snapshot()
+ )
+ if !evm.StateDB.Exist(addr) {
+ return nil, gas, nil
+ }
+
+ // initialise a new contract and set the code that is to be used by the
+ // EVM. The contract is a scoped evmironment for this execution context
+ // only.
+ contract := NewContract(caller, to, new(big.Int), gas)
+ contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
+
+ ret, err = evm.interpreter.Run(snapshot, contract, input)
+ // When an error was returned by the EVM or when setting the creation code
+ // above we revert to the snapshot and consume any gas remaining. Additionally
+ // when we're in homestead this also counts for code storage gas errors.
+ if err != nil {
+ contract.UseGas(contract.Gas)
+
+ evm.StateDB.RevertToSnapshot(snapshot)
+ }
+ return ret, contract.Gas, err
+}
+
// Create creates a new contract using code as deployment code.
func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
if evm.vmConfig.NoRecursion && evm.depth > 0 {