diff --git a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs index e54529f6d1..34db4fe3dd 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs @@ -449,6 +449,7 @@ protected internal Signer[] GetCurrentSigners() private static bool CheckItemType(StackItem item, ContractParameterType type) { StackItemType aType = item.Type; + if (aType == StackItemType.Any) return true; if (aType == StackItemType.Pointer) return false; switch (type) { @@ -459,7 +460,7 @@ private static bool CheckItemType(StackItem item, ContractParameterType type) case ContractParameterType.Integer: return aType == StackItemType.Integer; case ContractParameterType.ByteArray: - return aType is StackItemType.Any or StackItemType.ByteString or StackItemType.Buffer; + return aType is StackItemType.ByteString or StackItemType.Buffer; case ContractParameterType.String: { if (aType is StackItemType.ByteString or StackItemType.Buffer) @@ -474,27 +475,23 @@ private static bool CheckItemType(StackItem item, ContractParameterType type) return false; } case ContractParameterType.Hash160: - if (aType == StackItemType.Any) return true; if (aType != StackItemType.ByteString && aType != StackItemType.Buffer) return false; return item.GetSpan().Length == UInt160.Length; case ContractParameterType.Hash256: - if (aType == StackItemType.Any) return true; if (aType != StackItemType.ByteString && aType != StackItemType.Buffer) return false; return item.GetSpan().Length == UInt256.Length; case ContractParameterType.PublicKey: - if (aType == StackItemType.Any) return true; if (aType != StackItemType.ByteString && aType != StackItemType.Buffer) return false; return item.GetSpan().Length == 33; case ContractParameterType.Signature: - if (aType == StackItemType.Any) return true; if (aType != StackItemType.ByteString && aType != StackItemType.Buffer) return false; return item.GetSpan().Length == 64; case ContractParameterType.Array: - return aType is StackItemType.Any or StackItemType.Array or StackItemType.Struct; + return aType is StackItemType.Array or StackItemType.Struct; case ContractParameterType.Map: - return aType is StackItemType.Any or StackItemType.Map; + return aType is StackItemType.Map; case ContractParameterType.InteropInterface: - return aType is StackItemType.Any or StackItemType.InteropInterface; + return aType is StackItemType.InteropInterface; default: return false; } diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 6fd69439ab..bc77c29494 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -319,7 +319,11 @@ private ExecutionContext CallContractInternal(ContractState contract, ContractMe state.CallingContext = currentContext; for (int i = args.Count - 1; i >= 0; i--) + { + if (!CheckItemType(args[i], method.Parameters[i].Type)) + throw new InvalidOperationException($"The type of the argument `{args[i]}` does not match the formal parameter."); context_new.EvaluationStack.Push(args[i]); + } return context_new; } diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_GasToken.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_GasToken.cs index ebb66f0dff..635641854c 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_GasToken.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_GasToken.cs @@ -20,6 +20,7 @@ using System; using System.Linq; using System.Numerics; +using System.Reflection; using System.Threading.Tasks; namespace Neo.UnitTests.SmartContract.Native @@ -131,8 +132,8 @@ await Assert.ThrowsExceptionAsync(async () => // Bad inputs Assert.ThrowsException(() => NativeContract.GAS.Transfer(engine.Snapshot, from, to, BigInteger.MinusOne, true, persistingBlock)); - Assert.ThrowsException(() => NativeContract.GAS.Transfer(engine.Snapshot, new byte[19], to, BigInteger.One, false, persistingBlock)); - Assert.ThrowsException(() => NativeContract.GAS.Transfer(engine.Snapshot, from, new byte[19], BigInteger.One, false, persistingBlock)); + Assert.ThrowsException(() => NativeContract.GAS.Transfer(engine.Snapshot, new byte[19], to, BigInteger.One, false, persistingBlock)); + Assert.ThrowsException(() => NativeContract.GAS.Transfer(engine.Snapshot, from, new byte[19], BigInteger.One, false, persistingBlock)); } internal static StorageKey CreateStorageKey(byte prefix, uint key) diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NeoToken.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NeoToken.cs index b08898aad5..d81511ea19 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NeoToken.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NeoToken.cs @@ -23,6 +23,7 @@ using System; using System.Linq; using System.Numerics; +using System.Reflection; using static Neo.SmartContract.Native.NeoToken; namespace Neo.UnitTests.SmartContract.Native @@ -436,8 +437,8 @@ public void Check_Transfer() // Bad inputs Assert.ThrowsException(() => NativeContract.NEO.Transfer(snapshot, from, to, BigInteger.MinusOne, true, persistingBlock)); - Assert.ThrowsException(() => NativeContract.NEO.Transfer(snapshot, new byte[19], to, BigInteger.One, false, persistingBlock)); - Assert.ThrowsException(() => NativeContract.NEO.Transfer(snapshot, from, new byte[19], BigInteger.One, false, persistingBlock)); + Assert.ThrowsException(() => NativeContract.NEO.Transfer(snapshot, new byte[19], to, BigInteger.One, false, persistingBlock)); + Assert.ThrowsException(() => NativeContract.NEO.Transfer(snapshot, from, new byte[19], BigInteger.One, false, persistingBlock)); // More than balance diff --git a/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs b/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs index 48203a644a..ca54c205ff 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs @@ -57,7 +57,7 @@ public void Runtime_GetNotifications_Test() scriptHash2 = script.ToArray().ToScriptHash(); snapshot.DeleteContract(scriptHash2); - var contract = TestUtils.GetContract(script.ToArray(), TestUtils.CreateManifest("test", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer)); + var contract = TestUtils.GetContract(script.ToArray(), TestUtils.CreateManifest("test", ContractParameterType.Any, ContractParameterType.String, ContractParameterType.Integer)); contract.Manifest.Abi.Events = new[] { new ContractEventDescriptor