diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 4ecfdde31e..19e20b071f 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -30,14 +30,16 @@ partial class ApplicationEngine internal ContractState CreateContract(byte[] script, byte[] manifest) { - if (script.Length == 0 || script.Length > MaxContractLength || manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength) - throw new ArgumentException(); + if (script.Length == 0 || script.Length > MaxContractLength) + throw new ArgumentException($"Invalid Script Length: {script.Length}"); + if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength) + throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}"); AddGas(StoragePrice * (script.Length + manifest.Length)); UInt160 hash = script.ToScriptHash(); ContractState contract = Snapshot.Contracts.TryGet(hash); - if (contract != null) throw new InvalidOperationException(); + if (contract != null) throw new InvalidOperationException($"Contract Already Exists: {hash}"); contract = new ContractState { Id = Snapshot.ContractId.GetAndChange().NextId++, @@ -45,7 +47,7 @@ internal ContractState CreateContract(byte[] script, byte[] manifest) Manifest = ContractManifest.Parse(manifest) }; - if (!contract.Manifest.IsValid(hash)) throw new InvalidOperationException(); + if (!contract.Manifest.IsValid(hash)) throw new InvalidOperationException($"Invalid Manifest Hash: {hash}"); Snapshot.Contracts.Add(hash, contract); return contract; @@ -56,15 +58,15 @@ internal void UpdateContract(byte[] script, byte[] manifest) AddGas(StoragePrice * (script?.Length ?? 0 + manifest?.Length ?? 0)); var contract = Snapshot.Contracts.TryGet(CurrentScriptHash); - if (contract is null) throw new InvalidOperationException(); + if (contract is null) throw new InvalidOperationException($"Updating Contract Does Not Exist: {CurrentScriptHash}"); if (script != null) { if (script.Length == 0 || script.Length > MaxContractLength) - throw new ArgumentException(); + throw new ArgumentException($"Invalid Script Length: {script.Length}"); UInt160 hash_new = script.ToScriptHash(); if (hash_new.Equals(CurrentScriptHash) || Snapshot.Contracts.TryGet(hash_new) != null) - throw new InvalidOperationException(); + throw new InvalidOperationException($"Adding Contract Hash Already Exist: {hash_new}"); contract = new ContractState { Id = contract.Id, @@ -78,13 +80,13 @@ internal void UpdateContract(byte[] script, byte[] manifest) if (manifest != null) { if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength) - throw new ArgumentException(); + throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}"); contract = Snapshot.Contracts.GetAndChange(contract.ScriptHash); contract.Manifest = ContractManifest.Parse(manifest); if (!contract.Manifest.IsValid(contract.ScriptHash)) - throw new InvalidOperationException(); + throw new InvalidOperationException($"Invalid Manifest Hash: {contract.ScriptHash}"); if (!contract.HasStorage && Snapshot.Storages.Find(BitConverter.GetBytes(contract.Id)).Any()) - throw new InvalidOperationException(); + throw new InvalidOperationException($"Contract Does Not Support Storage But Uses Storage"); } } @@ -113,15 +115,15 @@ internal void CallContractEx(UInt160 contractHash, string method, Array args, Ca private void CallContractInternal(UInt160 contractHash, string method, Array args, CallFlags flags) { - if (method.StartsWith('_')) throw new ArgumentException(); + if (method.StartsWith('_')) throw new ArgumentException($"Invalid Method Name: {method}"); ContractState contract = Snapshot.Contracts.TryGet(contractHash); - if (contract is null) throw new InvalidOperationException(); + if (contract is null) throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}"); ContractManifest currentManifest = Snapshot.Contracts.TryGet(CurrentScriptHash)?.Manifest; if (currentManifest != null && !currentManifest.CanCall(contract.Manifest, method)) - throw new InvalidOperationException(); + throw new InvalidOperationException($"Cannot Call Method {method} Of Contract {contractHash} From Contract {CurrentScriptHash}"); if (invocationCounter.TryGetValue(contract.ScriptHash, out var counter)) { @@ -139,8 +141,8 @@ private void CallContractInternal(UInt160 contractHash, string method, Array arg CallFlags callingFlags = state.CallFlags; ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method); - if (md is null) throw new InvalidOperationException(); - if (args.Count != md.Parameters.Length) throw new InvalidOperationException(); + if (md is null) throw new InvalidOperationException($"Method {method} Does Not Exist In Contract {contractHash}"); + if (args.Count != md.Parameters.Length) throw new InvalidOperationException($"Method {method} Expects {md.Parameters.Length} Arguments But Receives {args.Count} Arguments"); ExecutionContext context_new = LoadScript(contract.Script); state = context_new.GetState(); state.CallingScriptHash = callingScriptHash; diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index 4d4eaf4b07..95a7ad7b66 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -9,6 +9,7 @@ using Neo.SmartContract; using Neo.SmartContract.Iterators; using Neo.SmartContract.Manifest; +using Neo.SmartContract.Native; using Neo.VM.Types; using Neo.Wallets; using System; @@ -135,6 +136,15 @@ public void TestContract_Create() var manifest = TestUtils.CreateDefaultManifest(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")); Assert.ThrowsException(() => engine.CreateContract(script, manifest.ToJson().ToByteArray(false))); + var script_exceedMaxLength = new byte[ApplicationEngine.MaxContractLength + 1]; + Assert.ThrowsException(() => engine.CreateContract(script_exceedMaxLength, manifest.ToJson().ToByteArray(true))); + + var script_zeroLength = new byte[] { }; + Assert.ThrowsException(() => engine.CreateContract(script_zeroLength, manifest.ToJson().ToByteArray(true))); + + var manifest_zeroLength = new byte[] { }; + Assert.ThrowsException(() => engine.CreateContract(script, manifest_zeroLength)); + manifest.Abi.Hash = script.ToScriptHash(); engine.CreateContract(script, manifest.ToJson().ToByteArray(false));