diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index c52527bb6b..74149094aa 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -10,7 +10,7 @@ namespace Neo.SmartContract { partial class ApplicationEngine { - public static readonly InteropDescriptor System_Contract_Call = Register("System.Contract.Call", nameof(CallContract), 1 << 15, CallFlags.AllowCall); + public static readonly InteropDescriptor System_Contract_Call = Register("System.Contract.Call", nameof(CallContract), 1 << 15, CallFlags.ReadStates | CallFlags.AllowCall); public static readonly InteropDescriptor System_Contract_CallNative = Register("System.Contract.CallNative", nameof(CallNativeContract), 0, CallFlags.None); public static readonly InteropDescriptor System_Contract_IsStandard = Register("System.Contract.IsStandard", nameof(IsStandardContract), 1 << 10, CallFlags.ReadStates); public static readonly InteropDescriptor System_Contract_GetCallFlags = Register("System.Contract.GetCallFlags", nameof(GetCallFlags), 1 << 10, CallFlags.None); diff --git a/src/neo/SmartContract/ApplicationEngine.Runtime.cs b/src/neo/SmartContract/ApplicationEngine.Runtime.cs index 5a1edd1598..abefbdc575 100644 --- a/src/neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/neo/SmartContract/ApplicationEngine.Runtime.cs @@ -89,8 +89,7 @@ protected internal bool CheckWitnessInternal(UInt160 hash) { // Check allow state callflag - if (!CurrentContext.GetState().CallFlags.HasFlag(CallFlags.ReadStates)) - throw new InvalidOperationException($"Cannot call this SYSCALL without the flag AllowStates."); + ValidateCallFlags(CallFlags.ReadStates); var contract = NativeContract.ContractManagement.GetContract(Snapshot, CallingScriptHash); // check if current group is the required one @@ -102,8 +101,7 @@ protected internal bool CheckWitnessInternal(UInt160 hash) // Check allow state callflag - if (!CurrentContext.GetState().CallFlags.HasFlag(CallFlags.ReadStates)) - throw new InvalidOperationException($"Cannot call this SYSCALL without the flag AllowStates."); + ValidateCallFlags(CallFlags.ReadStates); // only for non-Transaction types (Block, etc) diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index 39c7f048cb..b16c238303 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -197,6 +197,7 @@ public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialP protected override ExecutionContext LoadToken(ushort tokenId) { + ValidateCallFlags(CallFlags.ReadStates | CallFlags.AllowCall); ContractState contract = CurrentContext.GetState().Contract; if (contract is null || tokenId >= contract.Nef.Tokens.Length) throw new InvalidOperationException(); @@ -281,17 +282,17 @@ public override void Dispose() base.Dispose(); } - protected void ValidateCallFlags(InteropDescriptor descriptor) + protected void ValidateCallFlags(CallFlags requiredCallFlags) { ExecutionContextState state = CurrentContext.GetState(); - if (!state.CallFlags.HasFlag(descriptor.RequiredCallFlags)) + if (!state.CallFlags.HasFlag(requiredCallFlags)) throw new InvalidOperationException($"Cannot call this SYSCALL with the flag {state.CallFlags}."); } protected override void OnSysCall(uint method) { InteropDescriptor descriptor = services[method]; - ValidateCallFlags(descriptor); + ValidateCallFlags(descriptor.RequiredCallFlags); AddGas(descriptor.FixedPrice * exec_fee_factor); List parameters = descriptor.Parameters.Count > 0 ? new List()