diff --git a/pkg/core/interop/contract/call.go b/pkg/core/interop/contract/call.go index 08f064c37..1a327e608 100644 --- a/pkg/core/interop/contract/call.go +++ b/pkg/core/interop/contract/call.go @@ -46,10 +46,13 @@ func callExInternal(ic *interop.Context, h []byte, name string, args []stackitem if strings.HasPrefix(name, "_") { return errors.New("invalid method name (starts with '_')") } - curr, err := ic.DAO.GetContractState(ic.VM.GetCurrentScriptHash()) - if err == nil { - if !curr.Manifest.CanCall(u, &cs.Manifest, name) { - return errors.New("disallowed method call") + ctx := ic.VM.Context() + if ctx != nil && ctx.IsDeployed() { + curr, err := ic.DAO.GetContractState(ic.VM.GetCurrentScriptHash()) + if err == nil { + if !curr.Manifest.CanCall(u, &cs.Manifest, name) { + return errors.New("disallowed method call") + } } } return CallExInternal(ic, cs, name, args, f, vm.EnsureNotEmpty, nil) diff --git a/pkg/core/interop_system_test.go b/pkg/core/interop_system_test.go index 11e80b7e2..b0f0c1e62 100644 --- a/pkg/core/interop_system_test.go +++ b/pkg/core/interop_system_test.go @@ -581,7 +581,7 @@ func TestContractCall(t *testing.T) { runInvalid := func(args ...interface{}) func(t *testing.T) { return func(t *testing.T) { - loadScript(ic, currScript, 42) + loadScriptWithHashAndFlags(ic, currScript, h, smartcontract.All, 42) for i := range args { ic.VM.Estack().PushVal(args[i]) } diff --git a/pkg/vm/context.go b/pkg/vm/context.go index 08d38b87a..85d6e2611 100644 --- a/pkg/vm/context.go +++ b/pkg/vm/context.go @@ -42,6 +42,9 @@ type Context struct { // Caller's contract script hash. callingScriptHash util.Uint160 + // Set to true when running deployed contracts. + isDeployed bool + // Call flags this context was created with. callFlag smartcontract.CallFlag @@ -256,6 +259,11 @@ func (c *Context) String() string { return "execution context" } +// IsDeployed returns whether this context contains deployed contract. +func (c *Context) IsDeployed() bool { + return c.isDeployed +} + // getContextScriptHash returns script hash of the invocation stack element // number n. func (v *VM) getContextScriptHash(n int) util.Uint160 { diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 03190378e..9fd3d4540 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -284,12 +284,16 @@ func (v *VM) LoadScriptWithFlags(b []byte, f smartcontract.CallFlag) { } // LoadScriptWithHash if similar to the LoadScriptWithFlags method, but it also loads -// given script hash directly into the Context to avoid its recalculations. It's -// up to user of this function to make sure the script and hash match each other. +// given script hash directly into the Context to avoid its recalculations and to make +// is possible to override it for deployed contracts with special hashes (the function +// assumes that it is used for deployed contracts setting context's parameters +// accordingly). It's up to user of this function to make sure the script and hash match +// each other. func (v *VM) LoadScriptWithHash(b []byte, hash util.Uint160, f smartcontract.CallFlag) { shash := v.GetCurrentScriptHash() v.LoadScriptWithFlags(b, f) ctx := v.Context() + ctx.isDeployed = true ctx.scriptHash = hash ctx.callingScriptHash = shash }