From e70a210dcd46ec3464c79128fcb1df5d7393b9c0 Mon Sep 17 00:00:00 2001 From: bettybao1209 <1062108372@qq.com> Date: Mon, 24 Feb 2020 17:32:36 +0800 Subject: [PATCH 1/6] dynamically adjust fees --- src/neo/SmartContract/ApplicationEngine.cs | 5 +- src/neo/SmartContract/Native/FeeContract.cs | 152 ++++++++++++++++++ .../SmartContract/Native/NativeContract.cs | 1 + src/neo/Wallets/Wallet.cs | 12 +- .../SmartContract/Native/UT_FeeContract.cs | 109 +++++++++++++ .../SmartContract/UT_InteropPrices.cs | 13 +- 6 files changed, 278 insertions(+), 14 deletions(-) create mode 100644 src/neo/SmartContract/Native/FeeContract.cs create mode 100644 tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index 53bc8c68a8..1b9d7dfdce 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -1,6 +1,7 @@ using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.Persistence; +using Neo.SmartContract.Native; using Neo.VM; using Neo.VM.Types; using System; @@ -78,7 +79,7 @@ public override void Dispose() protected override bool OnSysCall(uint method) { - if (!AddGas(InteropService.GetPrice(method, CurrentContext.EvaluationStack))) + if (!AddGas(NativeContract.Fee.GetSyscallPrice(method, CurrentContext.EvaluationStack))) return false; return InteropService.Invoke(this, method); } @@ -87,7 +88,7 @@ protected override bool PreExecuteInstruction() { if (CurrentContext.InstructionPointer >= CurrentContext.Script.Length) return true; - return AddGas(OpCodePrices[CurrentContext.CurrentInstruction.OpCode]); + return AddGas(NativeContract.Fee.GetOpCodePrice(CurrentContext.CurrentInstruction.OpCode)); } private static Block CreateDummyBlock(StoreView snapshot) diff --git a/src/neo/SmartContract/Native/FeeContract.cs b/src/neo/SmartContract/Native/FeeContract.cs new file mode 100644 index 0000000000..626490e88b --- /dev/null +++ b/src/neo/SmartContract/Native/FeeContract.cs @@ -0,0 +1,152 @@ +#pragma warning disable IDE0051 +#pragma warning disable IDE0060 + +using Neo.Ledger; +using Neo.Persistence; +using Neo.VM; +using Neo.VM.Types; +using System; +using System.Numerics; +using Array = Neo.VM.Types.Array; + +namespace Neo.SmartContract.Native +{ + public sealed class FeeContract : NativeContract + { + public override string ServiceName => "Neo.Native.Fee"; + public override int Id => -4; + + private const byte Prefix_Ratio = 11; + private const byte Prefix_Syscall = 12; + private const byte Prefix_OpCode = 13; + + internal FeeContract() + { + } + + internal override bool Initialize(ApplicationEngine engine) + { + if (!base.Initialize(engine)) return false; + engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Ratio), new StorageItem + { + Value = BitConverter.GetBytes(100u) + }); + return true; + } + + private bool CheckValidators(ApplicationEngine engine) + { + UInt256 prev_hash = engine.Snapshot.PersistingBlock.PrevHash; + TrimmedBlock prev_block = engine.Snapshot.Blocks[prev_hash]; + return InteropService.Runtime.CheckWitnessInternal(engine, prev_block.NextConsensus); + } + + [ContractMethod(0_00010000, ContractParameterType.Integer, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })] + private StackItem GetSyscallPrice(ApplicationEngine engine, Array args) + { + uint method = (uint)args[0].GetBigInteger(); + return GetSyscallPrice(method, null, engine.Snapshot); + } + + public long GetSyscallPrice(uint method, EvaluationStack stack = null, StoreView snapshot = null) + { + if (snapshot?.Storages.TryGet(CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method))) != null) + { + return BitConverter.ToInt64(snapshot?.Storages[CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method))].Value, 0); + } + return InteropService.GetPrice(method, stack); + } + + [ContractMethod(0_00030000, ContractParameterType.Integer, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })] + private StackItem SetSyscallPrice(ApplicationEngine engine, Array args) + { + if (!CheckValidators(engine)) return false; + uint method = (uint)args[0].GetBigInteger(); + long value = InteropService.GetPrice(method, engine.CurrentContext.EvaluationStack) / GetRatio(engine.Snapshot); + StorageItem storage = engine.Snapshot.Storages.TryGet(CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method))); + if (storage != null) + { + storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method))); + storage.Value = BitConverter.GetBytes(value); + } + else + { + engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method)), new StorageItem + { + Value = BitConverter.GetBytes(value) + }); + } + return true; + } + + [ContractMethod(0_00010000, ContractParameterType.Integer, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })] + private StackItem GetOpCodePrice(ApplicationEngine engine, Array args) + { + uint opCode = (uint)args[0].GetBigInteger(); + return GetOpCodePrice((OpCode)opCode, engine.Snapshot); + } + + public long GetOpCodePrice(OpCode opCode, StoreView snapshot = null) + { + if (snapshot?.Storages.TryGet(CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes((int)opCode))) != null) + { + return BitConverter.ToInt64(snapshot.Storages[CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes((int)opCode))].Value, 0); + } + return ApplicationEngine.OpCodePrices[opCode]; + } + + [ContractMethod(0_00030000, ContractParameterType.Integer, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })] + private StackItem SetOpCodePrice(ApplicationEngine engine, Array args) + { + if (!CheckValidators(engine)) return false; + uint opCode = (uint)args[0].GetBigInteger(); + long value = ApplicationEngine.OpCodePrices[(OpCode)opCode] / GetRatio(engine.Snapshot); + StorageItem storage = engine.Snapshot.Storages.TryGet(CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes(opCode))); + if (storage != null) + { + storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes(opCode))); + storage.Value = BitConverter.GetBytes(value); + } + else + { + engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes(opCode)), new StorageItem + { + Value = BitConverter.GetBytes(value) + }); + } + return true; + } + + /** + [ContractMethod(0_00030000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })] + private StackItem SetOpcodePrice(ApplicationEngine engine, Array args) + { + if (!CheckValidators(engine)) return false; + byte opCode = args[0].GetBigInteger().ToByteArray()[0]; + ApplicationEngine.OpCodePrices[(OpCode)opCode] / GetRatio(engine.Snapshot); + return true; + } + **/ + + [ContractMethod(0_00010000, ContractParameterType.Integer, SafeMethod = true)] + private StackItem GetRatio(ApplicationEngine engine, Array args) + { + return GetRatio(engine.Snapshot); + } + + public uint GetRatio(StoreView snapshot) + { + return BitConverter.ToUInt32(snapshot.Storages[CreateStorageKey(Prefix_Ratio)].Value, 0); + } + + [ContractMethod(0_00030000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })] + private StackItem SetRatio(ApplicationEngine engine, Array args) + { + if (!CheckValidators(engine)) return false; + uint value = (uint)args[0].GetBigInteger(); + StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Ratio)); + storage.Value = BitConverter.GetBytes(value); + return true; + } + } +} diff --git a/src/neo/SmartContract/Native/NativeContract.cs b/src/neo/SmartContract/Native/NativeContract.cs index b7c7f85251..91d1e19317 100644 --- a/src/neo/SmartContract/Native/NativeContract.cs +++ b/src/neo/SmartContract/Native/NativeContract.cs @@ -23,6 +23,7 @@ public abstract class NativeContract public static NeoToken NEO { get; } = new NeoToken(); public static GasToken GAS { get; } = new GasToken(); public static PolicyContract Policy { get; } = new PolicyContract(); + public static FeeContract Fee { get; } = new FeeContract(); public abstract string ServiceName { get; } public uint ServiceHash { get; } diff --git a/src/neo/Wallets/Wallet.cs b/src/neo/Wallets/Wallet.cs index 892cc40c1c..c59ad01a88 100644 --- a/src/neo/Wallets/Wallet.cs +++ b/src/neo/Wallets/Wallet.cs @@ -354,19 +354,19 @@ public static long CalculateNetworkFee(byte[] witness_script, ref int size) if (witness_script.IsSignatureContract()) { size += 67 + witness_script.GetVarSize(); - networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] + ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] + ApplicationEngine.OpCodePrices[OpCode.PUSHNULL] + InteropService.GetPrice(InteropService.Crypto.ECDsaVerify, null); + networkFee += NativeContract.Fee.GetOpCodePrice(OpCode.PUSHDATA1)+ NativeContract.Fee.GetOpCodePrice(OpCode.PUSHDATA1) + NativeContract.Fee.GetOpCodePrice(OpCode.PUSHNULL) + NativeContract.Fee.GetSyscallPrice(InteropService.Crypto.ECDsaVerify); } else if (witness_script.IsMultiSigContract(out int m, out int n)) { int size_inv = 66 * m; size += IO.Helper.GetVarSize(size_inv) + size_inv + witness_script.GetVarSize(); - networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] * m; + networkFee += NativeContract.Fee.GetOpCodePrice(OpCode.PUSHDATA1) * m; using (ScriptBuilder sb = new ScriptBuilder()) - networkFee += ApplicationEngine.OpCodePrices[(OpCode)sb.EmitPush(m).ToArray()[0]]; - networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] * n; + networkFee += NativeContract.Fee.GetOpCodePrice((OpCode)sb.EmitPush(m).ToArray()[0]); + networkFee += NativeContract.Fee.GetOpCodePrice(OpCode.PUSHDATA1) * n; using (ScriptBuilder sb = new ScriptBuilder()) - networkFee += ApplicationEngine.OpCodePrices[(OpCode)sb.EmitPush(n).ToArray()[0]]; - networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHNULL] + InteropService.GetPrice(InteropService.Crypto.ECDsaVerify, null) * n; + networkFee += NativeContract.Fee.GetOpCodePrice((OpCode)sb.EmitPush(n).ToArray()[0]); + networkFee += NativeContract.Fee.GetOpCodePrice(OpCode.PUSHNULL) + NativeContract.Fee.GetSyscallPrice(InteropService.Crypto.ECDsaVerify) * n; } else { diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs new file mode 100644 index 0000000000..7158f6f3ec --- /dev/null +++ b/tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs @@ -0,0 +1,109 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Ledger; +using Neo.Network.P2P.Payloads; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.UnitTests.Extensions; +using Neo.VM; +using System; +using System.Linq; + +namespace Neo.UnitTests.SmartContract.Native +{ + [TestClass] + public class UT_FeeContract + { + [TestInitialize] + public void TestSetup() + { + TestBlockchain.InitializeMockNeoSystem(); + } + + [TestMethod] + public void Check_SupportedStandards() => NativeContract.Fee.SupportedStandards().Should().BeEquivalentTo(new string[] { "NEP-10" }); + + [TestMethod] + public void Check_Initialize() + { + var snapshot = Blockchain.Singleton.GetSnapshot(); + var keyCount = snapshot.Storages.GetChangeSet().Count(); + + NativeContract.Fee.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue(); + + (keyCount + 1).Should().Be(snapshot.Storages.GetChangeSet().Count()); + + var ret = NativeContract.Fee.Call(snapshot, "getRatio"); + ret.Should().BeOfType(); + ret.GetBigInteger().Should().Be(100); + } + + [TestMethod] + public void Check_SetSyscallPrice() + { + var snapshot = Blockchain.Singleton.GetSnapshot(); + + uint runtimeCheckWitness = "System.Runtime.CheckWitness".ToInteropMethodHash(); + + // Fake blockchain + + snapshot.PersistingBlock = new Block() { Index = 1000, PrevHash = UInt256.Zero }; + snapshot.Blocks.Add(UInt256.Zero, new Neo.Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero }); + + NativeContract.Fee.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue(); + + // Without signature + + var ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(), + "setSyscallPrice", new ContractParameter(ContractParameterType.Integer) { Value = runtimeCheckWitness }); + ret.Should().BeOfType(); + ret.ToBoolean().Should().BeFalse(); + + // With signature + + ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero), + "setSyscallPrice", new ContractParameter(ContractParameterType.Integer) { Value = runtimeCheckWitness } ); + ret.Should().BeOfType(); + ret.ToBoolean().Should().BeTrue(); + + ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero), + "getSyscallPrice", new ContractParameter(ContractParameterType.Integer) { Value = runtimeCheckWitness }); + ret.Should().BeOfType(); + ret.GetBigInteger().Should().Be(3); + } + + [TestMethod] + public void Check_SetOpCodePrice() + { + var snapshot = Blockchain.Singleton.GetSnapshot(); + + int pushdata4 = (int)OpCode.PUSHDATA4; + + // Fake blockchain + + snapshot.PersistingBlock = new Block() { Index = 1000, PrevHash = UInt256.Zero }; + snapshot.Blocks.Add(UInt256.Zero, new Neo.Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero }); + + NativeContract.Fee.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue(); + + // Without signature + + var ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(), + "setOpCodePrice", new ContractParameter(ContractParameterType.Integer) { Value = pushdata4}); + ret.Should().BeOfType(); + ret.ToBoolean().Should().BeFalse(); + + // With signature + + ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero), + "setOpCodePrice", new ContractParameter(ContractParameterType.Integer) { Value = pushdata4 }); + ret.Should().BeOfType(); + ret.ToBoolean().Should().BeTrue(); + + ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero), + "getOpCodePrice", new ContractParameter(ContractParameterType.Integer) { Value = pushdata4 }); + ret.Should().BeOfType(); + ret.GetBigInteger().Should().Be(11); + } + } +} diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs b/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs index 19eb7a5d38..06542ba55d 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs @@ -1,6 +1,7 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.SmartContract; +using Neo.SmartContract.Native; using Neo.VM; namespace Neo.UnitTests.SmartContract @@ -16,7 +17,7 @@ public void ApplicationEngineFixedPrices() using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, 0)) { ae.LoadScript(SyscallSystemRuntimeCheckWitnessHash); - InteropService.GetPrice(InteropService.Runtime.CheckWitness, ae.CurrentContext.EvaluationStack).Should().Be(0_00030000L); + NativeContract.Fee.GetSyscallPrice(InteropService.Runtime.CheckWitness, ae.CurrentContext.EvaluationStack).Should().Be(0_000300L); } // System.Storage.GetContext: 9bf667ce (price is 1) @@ -24,7 +25,7 @@ public void ApplicationEngineFixedPrices() using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, 0)) { ae.LoadScript(SyscallSystemStorageGetContextHash); - InteropService.GetPrice(InteropService.Storage.GetContext, ae.CurrentContext.EvaluationStack).Should().Be(0_00000400L); + NativeContract.Fee.GetSyscallPrice(InteropService.Storage.GetContext, ae.CurrentContext.EvaluationStack).Should().Be(0_0000040L); } // System.Storage.Get: 925de831 (price is 100) @@ -32,7 +33,7 @@ public void ApplicationEngineFixedPrices() using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, 0)) { ae.LoadScript(SyscallSystemStorageGetHash); - InteropService.GetPrice(InteropService.Storage.Get, ae.CurrentContext.EvaluationStack).Should().Be(0_01000000L); + NativeContract.Fee.GetSyscallPrice(InteropService.Storage.Get, ae.CurrentContext.EvaluationStack).Should().Be(0_010000L); } } @@ -47,7 +48,7 @@ public void ApplicationEngineVariablePrices() ae.LoadScript(SyscallContractCreateHash00); debugger.StepInto(); // PUSHDATA1 debugger.StepInto(); // PUSHDATA1 - InteropService.GetPrice(InteropService.Contract.Create, ae.CurrentContext.EvaluationStack).Should().Be(0_00300000L); + NativeContract.Fee.GetSyscallPrice(InteropService.Contract.Create, ae.CurrentContext.EvaluationStack).Should().Be(0_003000L); } // System.Storage.Put: e63f1884 (requires push key and value) @@ -59,7 +60,7 @@ public void ApplicationEngineVariablePrices() debugger.StepInto(); // push 03 (length 1) debugger.StepInto(); // push 03 (length 1) debugger.StepInto(); // push 00 - InteropService.GetPrice(InteropService.Storage.Put, ae.CurrentContext.EvaluationStack).Should().Be(200000L); + NativeContract.Fee.GetSyscallPrice(InteropService.Storage.Put, ae.CurrentContext.EvaluationStack).Should().Be(2000L); } // System.Storage.PutEx: 73e19b3a (requires push key and value) @@ -71,7 +72,7 @@ public void ApplicationEngineVariablePrices() debugger.StepInto(); // push 03 (length 1) debugger.StepInto(); // push 03 (length 1) debugger.StepInto(); // push 00 - InteropService.GetPrice(InteropService.Storage.PutEx, ae.CurrentContext.EvaluationStack).Should().Be(200000L); + NativeContract.Fee.GetSyscallPrice(InteropService.Storage.PutEx, ae.CurrentContext.EvaluationStack).Should().Be(2000L); } } } From cabc08f61c42ad0b12582ee1548e5b062357e8b4 Mon Sep 17 00:00:00 2001 From: bettybao1209 <1062108372@qq.com> Date: Tue, 25 Feb 2020 11:50:29 +0800 Subject: [PATCH 2/6] add initiated value and modify set logic --- src/neo/SmartContract/InteropService.cs | 2 +- src/neo/SmartContract/Native/FeeContract.cs | 80 +++++++------------ .../SmartContract/Native/UT_FeeContract.cs | 39 ++++++--- .../SmartContract/UT_InteropPrices.cs | 12 +-- 4 files changed, 68 insertions(+), 65 deletions(-) diff --git a/src/neo/SmartContract/InteropService.cs b/src/neo/SmartContract/InteropService.cs index c87ad277ea..fb6726edf3 100644 --- a/src/neo/SmartContract/InteropService.cs +++ b/src/neo/SmartContract/InteropService.cs @@ -7,7 +7,7 @@ namespace Neo.SmartContract { public static partial class InteropService { - private static readonly Dictionary methods = new Dictionary(); + public static readonly Dictionary methods = new Dictionary(); static InteropService() { diff --git a/src/neo/SmartContract/Native/FeeContract.cs b/src/neo/SmartContract/Native/FeeContract.cs index 626490e88b..621cfae354 100644 --- a/src/neo/SmartContract/Native/FeeContract.cs +++ b/src/neo/SmartContract/Native/FeeContract.cs @@ -6,6 +6,7 @@ using Neo.VM; using Neo.VM.Types; using System; +using System.Collections.Generic; using System.Numerics; using Array = Neo.VM.Types.Array; @@ -27,10 +28,24 @@ internal FeeContract() internal override bool Initialize(ApplicationEngine engine) { if (!base.Initialize(engine)) return false; + foreach (KeyValuePair kv in InteropService.methods) + { + engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(kv.Key)), new StorageItem + { + Value = BitConverter.GetBytes(kv.Value.Price) + }); + } + foreach (KeyValuePair kv in ApplicationEngine.OpCodePrices) + { + engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes((uint)kv.Key)), new StorageItem + { + Value = BitConverter.GetBytes(kv.Value) + }); + } engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Ratio), new StorageItem { - Value = BitConverter.GetBytes(100u) - }); + Value = BitConverter.GetBytes(1u) + }); return true; } @@ -50,32 +65,21 @@ private StackItem GetSyscallPrice(ApplicationEngine engine, Array args) public long GetSyscallPrice(uint method, EvaluationStack stack = null, StoreView snapshot = null) { - if (snapshot?.Storages.TryGet(CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method))) != null) + if (snapshot != null) { - return BitConverter.ToInt64(snapshot?.Storages[CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method))].Value, 0); + return BitConverter.ToInt64(snapshot.Storages[CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method))].Value, 0) / GetRatio(snapshot); } return InteropService.GetPrice(method, stack); } - [ContractMethod(0_00030000, ContractParameterType.Integer, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })] + [ContractMethod(0_00030000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Array }, ParameterNames = new[] { "value" })] private StackItem SetSyscallPrice(ApplicationEngine engine, Array args) { if (!CheckValidators(engine)) return false; - uint method = (uint)args[0].GetBigInteger(); - long value = InteropService.GetPrice(method, engine.CurrentContext.EvaluationStack) / GetRatio(engine.Snapshot); - StorageItem storage = engine.Snapshot.Storages.TryGet(CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method))); - if (storage != null) - { - storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method))); - storage.Value = BitConverter.GetBytes(value); - } - else - { - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method)), new StorageItem - { - Value = BitConverter.GetBytes(value) - }); - } + uint method = (uint)((Array)args[0])[0].GetBigInteger(); + ulong value = (ulong)((Array)args[0])[1].GetBigInteger(); + StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method))); + storage.Value = BitConverter.GetBytes(value); return true; } @@ -88,45 +92,23 @@ private StackItem GetOpCodePrice(ApplicationEngine engine, Array args) public long GetOpCodePrice(OpCode opCode, StoreView snapshot = null) { - if (snapshot?.Storages.TryGet(CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes((int)opCode))) != null) + if (snapshot != null) { - return BitConverter.ToInt64(snapshot.Storages[CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes((int)opCode))].Value, 0); + return BitConverter.ToInt64(snapshot.Storages[CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes((int)opCode))].Value, 0) / GetRatio(snapshot); } return ApplicationEngine.OpCodePrices[opCode]; } - [ContractMethod(0_00030000, ContractParameterType.Integer, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })] + [ContractMethod(0_00030000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Array }, ParameterNames = new[] { "value" })] private StackItem SetOpCodePrice(ApplicationEngine engine, Array args) { if (!CheckValidators(engine)) return false; - uint opCode = (uint)args[0].GetBigInteger(); - long value = ApplicationEngine.OpCodePrices[(OpCode)opCode] / GetRatio(engine.Snapshot); - StorageItem storage = engine.Snapshot.Storages.TryGet(CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes(opCode))); - if (storage != null) - { - storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes(opCode))); - storage.Value = BitConverter.GetBytes(value); - } - else - { - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes(opCode)), new StorageItem - { - Value = BitConverter.GetBytes(value) - }); - } - return true; - } - - /** - [ContractMethod(0_00030000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })] - private StackItem SetOpcodePrice(ApplicationEngine engine, Array args) - { - if (!CheckValidators(engine)) return false; - byte opCode = args[0].GetBigInteger().ToByteArray()[0]; - ApplicationEngine.OpCodePrices[(OpCode)opCode] / GetRatio(engine.Snapshot); + uint opCode = (uint)((Array)args[0])[0].GetBigInteger(); + ulong value = (ulong)((Array)args[0])[1].GetBigInteger(); + StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes(opCode))); + storage.Value = BitConverter.GetBytes(value); return true; } - **/ [ContractMethod(0_00010000, ContractParameterType.Integer, SafeMethod = true)] private StackItem GetRatio(ApplicationEngine engine, Array args) diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs index 7158f6f3ec..ebcc4bf551 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs @@ -7,6 +7,7 @@ using Neo.UnitTests.Extensions; using Neo.VM; using System; +using System.Collections.Generic; using System.Linq; namespace Neo.UnitTests.SmartContract.Native @@ -31,11 +32,23 @@ public void Check_Initialize() NativeContract.Fee.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue(); - (keyCount + 1).Should().Be(snapshot.Storages.GetChangeSet().Count()); + (keyCount + 232).Should().Be(snapshot.Storages.GetChangeSet().Count()); var ret = NativeContract.Fee.Call(snapshot, "getRatio"); ret.Should().BeOfType(); - ret.GetBigInteger().Should().Be(100); + ret.GetBigInteger().Should().Be(1u); + + uint runtimeCheckWitness = "System.Runtime.CheckWitness".ToInteropMethodHash(); + ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero), + "getSyscallPrice", new ContractParameter(ContractParameterType.Integer) { Value = runtimeCheckWitness }); + ret.Should().BeOfType(); + ret.GetBigInteger().Should().Be(30000); + + int pushdata4 = (int)OpCode.PUSHDATA4; + ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero), + "getOpCodePrice", new ContractParameter(ContractParameterType.Integer) { Value = pushdata4 }); + ret.Should().BeOfType(); + ret.GetBigInteger().Should().Be(110000); } [TestMethod] @@ -52,24 +65,28 @@ public void Check_SetSyscallPrice() NativeContract.Fee.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue(); + IList values = new List(); + values.Add(new ContractParameter { Type = ContractParameterType.Integer, Value = runtimeCheckWitness }); + values.Add(new ContractParameter { Type = ContractParameterType.Integer, Value = 300 }); + // Without signature var ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(), - "setSyscallPrice", new ContractParameter(ContractParameterType.Integer) { Value = runtimeCheckWitness }); + "setSyscallPrice", new ContractParameter(ContractParameterType.Array) { Value = values }); ret.Should().BeOfType(); ret.ToBoolean().Should().BeFalse(); // With signature - + ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero), - "setSyscallPrice", new ContractParameter(ContractParameterType.Integer) { Value = runtimeCheckWitness } ); + "setSyscallPrice", new ContractParameter(ContractParameterType.Array) { Value = values }); ret.Should().BeOfType(); ret.ToBoolean().Should().BeTrue(); ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero), "getSyscallPrice", new ContractParameter(ContractParameterType.Integer) { Value = runtimeCheckWitness }); ret.Should().BeOfType(); - ret.GetBigInteger().Should().Be(3); + ret.GetBigInteger().Should().Be(300); } [TestMethod] @@ -86,24 +103,28 @@ public void Check_SetOpCodePrice() NativeContract.Fee.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue(); + IList values = new List(); + values.Add(new ContractParameter { Type = ContractParameterType.Integer, Value = pushdata4 }); + values.Add(new ContractParameter { Type = ContractParameterType.Integer, Value = 1100 }); + // Without signature var ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(), - "setOpCodePrice", new ContractParameter(ContractParameterType.Integer) { Value = pushdata4}); + "setOpCodePrice", new ContractParameter(ContractParameterType.Array) { Value = values }); ret.Should().BeOfType(); ret.ToBoolean().Should().BeFalse(); // With signature ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero), - "setOpCodePrice", new ContractParameter(ContractParameterType.Integer) { Value = pushdata4 }); + "setOpCodePrice", new ContractParameter(ContractParameterType.Array) { Value = values }); ret.Should().BeOfType(); ret.ToBoolean().Should().BeTrue(); ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero), "getOpCodePrice", new ContractParameter(ContractParameterType.Integer) { Value = pushdata4 }); ret.Should().BeOfType(); - ret.GetBigInteger().Should().Be(11); + ret.GetBigInteger().Should().Be(1100); } } } diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs b/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs index 06542ba55d..ee38c93224 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs @@ -17,7 +17,7 @@ public void ApplicationEngineFixedPrices() using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, 0)) { ae.LoadScript(SyscallSystemRuntimeCheckWitnessHash); - NativeContract.Fee.GetSyscallPrice(InteropService.Runtime.CheckWitness, ae.CurrentContext.EvaluationStack).Should().Be(0_000300L); + NativeContract.Fee.GetSyscallPrice(InteropService.Runtime.CheckWitness, ae.CurrentContext.EvaluationStack).Should().Be(0_00030000L); } // System.Storage.GetContext: 9bf667ce (price is 1) @@ -25,7 +25,7 @@ public void ApplicationEngineFixedPrices() using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, 0)) { ae.LoadScript(SyscallSystemStorageGetContextHash); - NativeContract.Fee.GetSyscallPrice(InteropService.Storage.GetContext, ae.CurrentContext.EvaluationStack).Should().Be(0_0000040L); + NativeContract.Fee.GetSyscallPrice(InteropService.Storage.GetContext, ae.CurrentContext.EvaluationStack).Should().Be(0_00000400L); } // System.Storage.Get: 925de831 (price is 100) @@ -33,7 +33,7 @@ public void ApplicationEngineFixedPrices() using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, 0)) { ae.LoadScript(SyscallSystemStorageGetHash); - NativeContract.Fee.GetSyscallPrice(InteropService.Storage.Get, ae.CurrentContext.EvaluationStack).Should().Be(0_010000L); + NativeContract.Fee.GetSyscallPrice(InteropService.Storage.Get, ae.CurrentContext.EvaluationStack).Should().Be(0_01000000L); } } @@ -48,7 +48,7 @@ public void ApplicationEngineVariablePrices() ae.LoadScript(SyscallContractCreateHash00); debugger.StepInto(); // PUSHDATA1 debugger.StepInto(); // PUSHDATA1 - NativeContract.Fee.GetSyscallPrice(InteropService.Contract.Create, ae.CurrentContext.EvaluationStack).Should().Be(0_003000L); + NativeContract.Fee.GetSyscallPrice(InteropService.Contract.Create, ae.CurrentContext.EvaluationStack).Should().Be(0_00300000L); } // System.Storage.Put: e63f1884 (requires push key and value) @@ -60,7 +60,7 @@ public void ApplicationEngineVariablePrices() debugger.StepInto(); // push 03 (length 1) debugger.StepInto(); // push 03 (length 1) debugger.StepInto(); // push 00 - NativeContract.Fee.GetSyscallPrice(InteropService.Storage.Put, ae.CurrentContext.EvaluationStack).Should().Be(2000L); + NativeContract.Fee.GetSyscallPrice(InteropService.Storage.Put, ae.CurrentContext.EvaluationStack).Should().Be(200000L); } // System.Storage.PutEx: 73e19b3a (requires push key and value) @@ -72,7 +72,7 @@ public void ApplicationEngineVariablePrices() debugger.StepInto(); // push 03 (length 1) debugger.StepInto(); // push 03 (length 1) debugger.StepInto(); // push 00 - NativeContract.Fee.GetSyscallPrice(InteropService.Storage.PutEx, ae.CurrentContext.EvaluationStack).Should().Be(2000L); + NativeContract.Fee.GetSyscallPrice(InteropService.Storage.PutEx, ae.CurrentContext.EvaluationStack).Should().Be(200000L); } } } From b360a3f115ad21f073c2d607079469e47ab4eed4 Mon Sep 17 00:00:00 2001 From: bettybao1209 <1062108372@qq.com> Date: Tue, 25 Feb 2020 17:46:43 +0800 Subject: [PATCH 3/6] remove initiate --- src/neo/SmartContract/ApplicationEngine.cs | 4 +- src/neo/SmartContract/Native/FeeContract.cs | 53 +++++++++---------- src/neo/Wallets/Wallet.cs | 16 +++--- .../Nep5NativeContractExtensions.cs | 16 +++--- .../Native/Tokens/UT_GasToken.cs | 8 +-- .../Native/Tokens/UT_NeoToken.cs | 8 +-- .../SmartContract/Native/UT_FeeContract.cs | 16 +----- .../SmartContract/Native/UT_PolicyContract.cs | 2 +- .../SmartContract/UT_ApplicationEngine.cs | 4 +- .../SmartContract/UT_InteropPrices.cs | 29 ++++++---- .../SmartContract/UT_Syscalls.cs | 10 ++-- 11 files changed, 79 insertions(+), 87 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index 1b9d7dfdce..fffbce2da1 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -79,7 +79,7 @@ public override void Dispose() protected override bool OnSysCall(uint method) { - if (!AddGas(NativeContract.Fee.GetSyscallPrice(method, CurrentContext.EvaluationStack))) + if (!AddGas(NativeContract.Fee.GetSyscallPrice(method, Snapshot, CurrentContext.EvaluationStack))) return false; return InteropService.Invoke(this, method); } @@ -88,7 +88,7 @@ protected override bool PreExecuteInstruction() { if (CurrentContext.InstructionPointer >= CurrentContext.Script.Length) return true; - return AddGas(NativeContract.Fee.GetOpCodePrice(CurrentContext.CurrentInstruction.OpCode)); + return AddGas(NativeContract.Fee.GetOpCodePrice(CurrentContext.CurrentInstruction.OpCode, Snapshot)); } private static Block CreateDummyBlock(StoreView snapshot) diff --git a/src/neo/SmartContract/Native/FeeContract.cs b/src/neo/SmartContract/Native/FeeContract.cs index 621cfae354..1cb2e44e12 100644 --- a/src/neo/SmartContract/Native/FeeContract.cs +++ b/src/neo/SmartContract/Native/FeeContract.cs @@ -3,6 +3,7 @@ using Neo.Ledger; using Neo.Persistence; +using Neo.SmartContract.Manifest; using Neo.VM; using Neo.VM.Types; using System; @@ -21,27 +22,14 @@ public sealed class FeeContract : NativeContract private const byte Prefix_Syscall = 12; private const byte Prefix_OpCode = 13; - internal FeeContract() + public FeeContract() { + Manifest.Features = ContractFeatures.HasStorage; } internal override bool Initialize(ApplicationEngine engine) { if (!base.Initialize(engine)) return false; - foreach (KeyValuePair kv in InteropService.methods) - { - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(kv.Key)), new StorageItem - { - Value = BitConverter.GetBytes(kv.Value.Price) - }); - } - foreach (KeyValuePair kv in ApplicationEngine.OpCodePrices) - { - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes((uint)kv.Key)), new StorageItem - { - Value = BitConverter.GetBytes(kv.Value) - }); - } engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Ratio), new StorageItem { Value = BitConverter.GetBytes(1u) @@ -60,16 +48,16 @@ private bool CheckValidators(ApplicationEngine engine) private StackItem GetSyscallPrice(ApplicationEngine engine, Array args) { uint method = (uint)args[0].GetBigInteger(); - return GetSyscallPrice(method, null, engine.Snapshot); + return GetSyscallPrice(method, engine.Snapshot); } - public long GetSyscallPrice(uint method, EvaluationStack stack = null, StoreView snapshot = null) + public long GetSyscallPrice(uint method, StoreView snapshot, EvaluationStack stack = null) { - if (snapshot != null) + if (snapshot.Storages.TryGet(CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method))) != null) { return BitConverter.ToInt64(snapshot.Storages[CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method))].Value, 0) / GetRatio(snapshot); } - return InteropService.GetPrice(method, stack); + return InteropService.GetPrice(method, stack) / GetRatio(snapshot); } [ContractMethod(0_00030000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Array }, ParameterNames = new[] { "value" })] @@ -77,9 +65,10 @@ private StackItem SetSyscallPrice(ApplicationEngine engine, Array args) { if (!CheckValidators(engine)) return false; uint method = (uint)((Array)args[0])[0].GetBigInteger(); - ulong value = (ulong)((Array)args[0])[1].GetBigInteger(); - StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method))); - storage.Value = BitConverter.GetBytes(value); + long value = (long)((Array)args[0])[1].GetBigInteger(); + StorageKey key = CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method)); + StorageItem item = engine.Snapshot.Storages.GetAndChange(key, () => new StorageItem()); + item.Value = BitConverter.GetBytes(value); return true; } @@ -90,13 +79,13 @@ private StackItem GetOpCodePrice(ApplicationEngine engine, Array args) return GetOpCodePrice((OpCode)opCode, engine.Snapshot); } - public long GetOpCodePrice(OpCode opCode, StoreView snapshot = null) + public long GetOpCodePrice(OpCode opCode, StoreView snapshot) { - if (snapshot != null) + if (snapshot.Storages.TryGet(CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes((int)opCode))) != null) { return BitConverter.ToInt64(snapshot.Storages[CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes((int)opCode))].Value, 0) / GetRatio(snapshot); } - return ApplicationEngine.OpCodePrices[opCode]; + return ApplicationEngine.OpCodePrices[opCode] / GetRatio(snapshot); } [ContractMethod(0_00030000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Array }, ParameterNames = new[] { "value" })] @@ -104,9 +93,10 @@ private StackItem SetOpCodePrice(ApplicationEngine engine, Array args) { if (!CheckValidators(engine)) return false; uint opCode = (uint)((Array)args[0])[0].GetBigInteger(); - ulong value = (ulong)((Array)args[0])[1].GetBigInteger(); - StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes(opCode))); - storage.Value = BitConverter.GetBytes(value); + long value = (long)((Array)args[0])[1].GetBigInteger(); + StorageKey key = CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes(opCode)); + StorageItem item = engine.Snapshot.Storages.GetAndChange(key, () => new StorageItem()); + item.Value = BitConverter.GetBytes(value); return true; } @@ -118,7 +108,10 @@ private StackItem GetRatio(ApplicationEngine engine, Array args) public uint GetRatio(StoreView snapshot) { - return BitConverter.ToUInt32(snapshot.Storages[CreateStorageKey(Prefix_Ratio)].Value, 0); + if (snapshot.Storages.TryGet(CreateStorageKey(Prefix_Ratio)) != null) + return BitConverter.ToUInt32(snapshot.Storages[CreateStorageKey(Prefix_Ratio)].Value, 0); + else + return 1; } [ContractMethod(0_00030000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })] @@ -126,6 +119,8 @@ private StackItem SetRatio(ApplicationEngine engine, Array args) { if (!CheckValidators(engine)) return false; uint value = (uint)args[0].GetBigInteger(); + if (value == 0) + return false; StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Ratio)); storage.Value = BitConverter.GetBytes(value); return true; diff --git a/src/neo/Wallets/Wallet.cs b/src/neo/Wallets/Wallet.cs index c59ad01a88..ca2d87b365 100644 --- a/src/neo/Wallets/Wallet.cs +++ b/src/neo/Wallets/Wallet.cs @@ -339,7 +339,7 @@ private Transaction MakeTransaction(StoreView snapshot, byte[] script, Transacti { byte[] witness_script = GetAccount(hash)?.Contract?.Script ?? snapshot.Contracts.TryGet(hash)?.Script; if (witness_script is null) continue; - tx.NetworkFee += CalculateNetworkFee(witness_script, ref size); + tx.NetworkFee += CalculateNetworkFee(witness_script, ref size, snapshot); } tx.NetworkFee += size * NativeContract.Policy.GetFeePerByte(snapshot); if (value >= tx.SystemFee + tx.NetworkFee) return tx; @@ -347,26 +347,26 @@ private Transaction MakeTransaction(StoreView snapshot, byte[] script, Transacti throw new InvalidOperationException("Insufficient GAS"); } - public static long CalculateNetworkFee(byte[] witness_script, ref int size) + public static long CalculateNetworkFee(byte[] witness_script, ref int size, StoreView snapshot) { long networkFee = 0; if (witness_script.IsSignatureContract()) { size += 67 + witness_script.GetVarSize(); - networkFee += NativeContract.Fee.GetOpCodePrice(OpCode.PUSHDATA1)+ NativeContract.Fee.GetOpCodePrice(OpCode.PUSHDATA1) + NativeContract.Fee.GetOpCodePrice(OpCode.PUSHNULL) + NativeContract.Fee.GetSyscallPrice(InteropService.Crypto.ECDsaVerify); + networkFee += NativeContract.Fee.GetOpCodePrice(OpCode.PUSHDATA1, snapshot) + NativeContract.Fee.GetOpCodePrice(OpCode.PUSHDATA1, snapshot) + NativeContract.Fee.GetOpCodePrice(OpCode.PUSHNULL, snapshot) + NativeContract.Fee.GetSyscallPrice(InteropService.Crypto.ECDsaVerify, snapshot); } else if (witness_script.IsMultiSigContract(out int m, out int n)) { int size_inv = 66 * m; size += IO.Helper.GetVarSize(size_inv) + size_inv + witness_script.GetVarSize(); - networkFee += NativeContract.Fee.GetOpCodePrice(OpCode.PUSHDATA1) * m; + networkFee += NativeContract.Fee.GetOpCodePrice(OpCode.PUSHDATA1, snapshot) * m; using (ScriptBuilder sb = new ScriptBuilder()) - networkFee += NativeContract.Fee.GetOpCodePrice((OpCode)sb.EmitPush(m).ToArray()[0]); - networkFee += NativeContract.Fee.GetOpCodePrice(OpCode.PUSHDATA1) * n; + networkFee += NativeContract.Fee.GetOpCodePrice((OpCode)sb.EmitPush(m).ToArray()[0], snapshot); + networkFee += NativeContract.Fee.GetOpCodePrice(OpCode.PUSHDATA1, snapshot) * n; using (ScriptBuilder sb = new ScriptBuilder()) - networkFee += NativeContract.Fee.GetOpCodePrice((OpCode)sb.EmitPush(n).ToArray()[0]); - networkFee += NativeContract.Fee.GetOpCodePrice(OpCode.PUSHNULL) + NativeContract.Fee.GetSyscallPrice(InteropService.Crypto.ECDsaVerify) * n; + networkFee += NativeContract.Fee.GetOpCodePrice((OpCode)sb.EmitPush(n).ToArray()[0], snapshot); + networkFee += NativeContract.Fee.GetOpCodePrice(OpCode.PUSHNULL, snapshot) + NativeContract.Fee.GetSyscallPrice(InteropService.Crypto.ECDsaVerify, snapshot) * n; } else { diff --git a/tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs b/tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs index 4a04d97c84..938420690c 100644 --- a/tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs +++ b/tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs @@ -68,9 +68,9 @@ public static bool Transfer(this NativeContract contract, StoreView snapshot, by return result.ToBoolean(); } - public static string[] SupportedStandards(this NativeContract contract) + public static string[] SupportedStandards(this NativeContract contract, StoreView snapshot) { - var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, testMode: true); + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, testMode: true); engine.LoadScript(contract.Script); @@ -131,9 +131,9 @@ public static BigInteger BalanceOf(this NativeContract contract, StoreView snaps return (result as VM.Types.Integer).GetBigInteger(); } - public static BigInteger Decimals(this NativeContract contract) + public static BigInteger Decimals(this NativeContract contract, StoreView snapshot) { - var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, testMode: true); + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, testMode: true); engine.LoadScript(contract.Script); @@ -151,9 +151,9 @@ public static BigInteger Decimals(this NativeContract contract) return (result as VM.Types.Integer).GetBigInteger(); } - public static string Symbol(this NativeContract contract) + public static string Symbol(this NativeContract contract, StoreView snapshot) { - var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, testMode: true); + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, testMode: true); engine.LoadScript(contract.Script); @@ -171,9 +171,9 @@ public static string Symbol(this NativeContract contract) return result.GetString(); } - public static string Name(this NativeContract contract) + public static string Name(this NativeContract contract, StoreView snapshot) { - var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, testMode: true); + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, testMode: true); engine.LoadScript(contract.Script); diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs index 614322aa20..7fd27291a1 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs @@ -24,16 +24,16 @@ public void TestSetup() } [TestMethod] - public void Check_Name() => NativeContract.GAS.Name().Should().Be("GAS"); + public void Check_Name() => NativeContract.GAS.Name(Blockchain.Singleton.GetSnapshot()).Should().Be("GAS"); [TestMethod] - public void Check_Symbol() => NativeContract.GAS.Symbol().Should().Be("gas"); + public void Check_Symbol() => NativeContract.GAS.Symbol(Blockchain.Singleton.GetSnapshot()).Should().Be("gas"); [TestMethod] - public void Check_Decimals() => NativeContract.GAS.Decimals().Should().Be(8); + public void Check_Decimals() => NativeContract.GAS.Decimals(Blockchain.Singleton.GetSnapshot()).Should().Be(8); [TestMethod] - public void Check_SupportedStandards() => NativeContract.GAS.SupportedStandards().Should().BeEquivalentTo(new string[] { "NEP-5", "NEP-10" }); + public void Check_SupportedStandards() => NativeContract.GAS.SupportedStandards(Blockchain.Singleton.GetSnapshot()).Should().BeEquivalentTo(new string[] { "NEP-5", "NEP-10" }); [TestMethod] public void Check_BalanceOfTransferAndBurn() diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 6533b07541..6ab9e0a22f 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -28,16 +28,16 @@ public void TestSetup() } [TestMethod] - public void Check_Name() => NativeContract.NEO.Name().Should().Be("NEO"); + public void Check_Name() => NativeContract.NEO.Name(Blockchain.Singleton.GetSnapshot()).Should().Be("NEO"); [TestMethod] - public void Check_Symbol() => NativeContract.NEO.Symbol().Should().Be("neo"); + public void Check_Symbol() => NativeContract.NEO.Symbol(Blockchain.Singleton.GetSnapshot()).Should().Be("neo"); [TestMethod] - public void Check_Decimals() => NativeContract.NEO.Decimals().Should().Be(0); + public void Check_Decimals() => NativeContract.NEO.Decimals(Blockchain.Singleton.GetSnapshot()).Should().Be(0); [TestMethod] - public void Check_SupportedStandards() => NativeContract.NEO.SupportedStandards().Should().BeEquivalentTo(new string[] { "NEP-5", "NEP-10" }); + public void Check_SupportedStandards() => NativeContract.NEO.SupportedStandards(Blockchain.Singleton.GetSnapshot()).Should().BeEquivalentTo(new string[] { "NEP-5", "NEP-10" }); [TestMethod] public void Check_Vote() diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs index ebcc4bf551..a949fff619 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs @@ -22,7 +22,7 @@ public void TestSetup() } [TestMethod] - public void Check_SupportedStandards() => NativeContract.Fee.SupportedStandards().Should().BeEquivalentTo(new string[] { "NEP-10" }); + public void Check_SupportedStandards() => NativeContract.Fee.SupportedStandards(Blockchain.Singleton.GetSnapshot()).Should().BeEquivalentTo(new string[] { "NEP-10" }); [TestMethod] public void Check_Initialize() @@ -32,23 +32,11 @@ public void Check_Initialize() NativeContract.Fee.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue(); - (keyCount + 232).Should().Be(snapshot.Storages.GetChangeSet().Count()); + (keyCount + 1).Should().Be(snapshot.Storages.GetChangeSet().Count()); var ret = NativeContract.Fee.Call(snapshot, "getRatio"); ret.Should().BeOfType(); ret.GetBigInteger().Should().Be(1u); - - uint runtimeCheckWitness = "System.Runtime.CheckWitness".ToInteropMethodHash(); - ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero), - "getSyscallPrice", new ContractParameter(ContractParameterType.Integer) { Value = runtimeCheckWitness }); - ret.Should().BeOfType(); - ret.GetBigInteger().Should().Be(30000); - - int pushdata4 = (int)OpCode.PUSHDATA4; - ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero), - "getOpCodePrice", new ContractParameter(ContractParameterType.Integer) { Value = pushdata4 }); - ret.Should().BeOfType(); - ret.GetBigInteger().Should().Be(110000); } [TestMethod] diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs index a173585182..23e0434ec0 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs @@ -22,7 +22,7 @@ public void TestSetup() } [TestMethod] - public void Check_SupportedStandards() => NativeContract.Policy.SupportedStandards().Should().BeEquivalentTo(new string[] { "NEP-10" }); + public void Check_SupportedStandards() => NativeContract.Policy.SupportedStandards(Blockchain.Singleton.GetSnapshot()).Should().BeEquivalentTo(new string[] { "NEP-10" }); [TestMethod] public void Check_Initialize() diff --git a/tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.cs b/tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.cs index 71e8dfe759..06ad074047 100644 --- a/tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.cs +++ b/tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.cs @@ -119,13 +119,13 @@ public void TestCreateDummyBlock() [TestMethod] public void TestOnSysCall() { + var snapshot = Blockchain.Singleton.GetSnapshot(); InteropDescriptor descriptor = new InteropDescriptor("System.Blockchain.GetHeight", Blockchain_GetHeight, 0_00000400, TriggerType.Application, CallFlags.None); - TestApplicationEngine engine = new TestApplicationEngine(TriggerType.Application, null, null, 0); + TestApplicationEngine engine = new TestApplicationEngine(TriggerType.Application, null, snapshot, 0); byte[] SyscallSystemRuntimeCheckWitnessHash = new byte[] { 0x68, 0xf8, 0x27, 0xec, 0x8c }; engine.LoadScript(SyscallSystemRuntimeCheckWitnessHash); engine.GetOnSysCall(descriptor.Hash).Should().BeFalse(); - var snapshot = Blockchain.Singleton.GetSnapshot(); engine = new TestApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(SyscallSystemRuntimeCheckWitnessHash); engine.GetOnSysCall(descriptor.Hash).Should().BeTrue(); diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs b/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs index ee38c93224..e2b74784de 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs @@ -1,5 +1,6 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Ledger; using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.VM; @@ -9,15 +10,22 @@ namespace Neo.UnitTests.SmartContract [TestClass] public class UT_InteropPrices { + [TestInitialize] + public void TestSetup() + { + TestBlockchain.InitializeMockNeoSystem(); + } + [TestMethod] public void ApplicationEngineFixedPrices() { + var snapshot = Blockchain.Singleton.GetSnapshot(); // System.Runtime.CheckWitness: f827ec8c (price is 200) byte[] SyscallSystemRuntimeCheckWitnessHash = new byte[] { 0x68, 0xf8, 0x27, 0xec, 0x8c }; - using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, 0)) + using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, snapshot, 0)) { ae.LoadScript(SyscallSystemRuntimeCheckWitnessHash); - NativeContract.Fee.GetSyscallPrice(InteropService.Runtime.CheckWitness, ae.CurrentContext.EvaluationStack).Should().Be(0_00030000L); + NativeContract.Fee.GetSyscallPrice(InteropService.Runtime.CheckWitness, snapshot, ae.CurrentContext.EvaluationStack).Should().Be(0_00030000L); } // System.Storage.GetContext: 9bf667ce (price is 1) @@ -25,7 +33,7 @@ public void ApplicationEngineFixedPrices() using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, 0)) { ae.LoadScript(SyscallSystemStorageGetContextHash); - NativeContract.Fee.GetSyscallPrice(InteropService.Storage.GetContext, ae.CurrentContext.EvaluationStack).Should().Be(0_00000400L); + NativeContract.Fee.GetSyscallPrice(InteropService.Storage.GetContext, snapshot, ae.CurrentContext.EvaluationStack).Should().Be(0_00000400L); } // System.Storage.Get: 925de831 (price is 100) @@ -33,46 +41,47 @@ public void ApplicationEngineFixedPrices() using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, 0)) { ae.LoadScript(SyscallSystemStorageGetHash); - NativeContract.Fee.GetSyscallPrice(InteropService.Storage.Get, ae.CurrentContext.EvaluationStack).Should().Be(0_01000000L); + NativeContract.Fee.GetSyscallPrice(InteropService.Storage.Get, snapshot, ae.CurrentContext.EvaluationStack).Should().Be(0_01000000L); } } [TestMethod] public void ApplicationEngineVariablePrices() { + var snapshot = Blockchain.Singleton.GetSnapshot(); // Neo.Contract.Create: f66ca56e (requires push properties on fourth position) byte[] SyscallContractCreateHash00 = new byte[] { (byte)OpCode.PUSHDATA1, 0x01, 0x00, (byte)OpCode.PUSHDATA1, 0x02, 0x00, 0x00, (byte)OpCode.SYSCALL, 0xf6, 0x6c, 0xa5, 0x6e }; - using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, 0, testMode: true)) + using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, testMode: true)) { Debugger debugger = new Debugger(ae); ae.LoadScript(SyscallContractCreateHash00); debugger.StepInto(); // PUSHDATA1 debugger.StepInto(); // PUSHDATA1 - NativeContract.Fee.GetSyscallPrice(InteropService.Contract.Create, ae.CurrentContext.EvaluationStack).Should().Be(0_00300000L); + NativeContract.Fee.GetSyscallPrice(InteropService.Contract.Create, snapshot, ae.CurrentContext.EvaluationStack).Should().Be(0_00300000L); } // System.Storage.Put: e63f1884 (requires push key and value) byte[] SyscallStoragePutHash = new byte[] { (byte)OpCode.PUSH3, (byte)OpCode.PUSH3, (byte)OpCode.PUSH0, (byte)OpCode.SYSCALL, 0xe6, 0x3f, 0x18, 0x84 }; - using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, 0, testMode: true)) + using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, testMode: true)) { Debugger debugger = new Debugger(ae); ae.LoadScript(SyscallStoragePutHash); debugger.StepInto(); // push 03 (length 1) debugger.StepInto(); // push 03 (length 1) debugger.StepInto(); // push 00 - NativeContract.Fee.GetSyscallPrice(InteropService.Storage.Put, ae.CurrentContext.EvaluationStack).Should().Be(200000L); + NativeContract.Fee.GetSyscallPrice(InteropService.Storage.Put, snapshot, ae.CurrentContext.EvaluationStack).Should().Be(200000L); } // System.Storage.PutEx: 73e19b3a (requires push key and value) byte[] SyscallStoragePutExHash = new byte[] { (byte)OpCode.PUSH3, (byte)OpCode.PUSH3, (byte)OpCode.PUSH0, (byte)OpCode.SYSCALL, 0x73, 0xe1, 0x9b, 0x3a }; - using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, 0, testMode: true)) + using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, testMode: true)) { Debugger debugger = new Debugger(ae); ae.LoadScript(SyscallStoragePutExHash); debugger.StepInto(); // push 03 (length 1) debugger.StepInto(); // push 03 (length 1) debugger.StepInto(); // push 00 - NativeContract.Fee.GetSyscallPrice(InteropService.Storage.PutEx, ae.CurrentContext.EvaluationStack).Should().Be(200000L); + NativeContract.Fee.GetSyscallPrice(InteropService.Storage.PutEx, snapshot, ae.CurrentContext.EvaluationStack).Should().Be(200000L); } } } diff --git a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs index 04f60db7ff..35829f9248 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -96,7 +96,7 @@ public void System_Blockchain_GetBlock() public void Json_Deserialize() { // Good - + var snapshot = Blockchain.Singleton.GetSnapshot(); using (var script = new ScriptBuilder()) { script.EmitPush("123"); @@ -104,7 +104,7 @@ public void Json_Deserialize() script.EmitPush("null"); script.EmitSysCall(InteropService.Json.Deserialize); - using (var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, true)) + using (var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true)) { engine.LoadScript(script.ToArray()); @@ -123,7 +123,7 @@ public void Json_Deserialize() script.EmitPush("***"); script.EmitSysCall(InteropService.Json.Deserialize); - using (var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, true)) + using (var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true)) { engine.LoadScript(script.ToArray()); @@ -153,7 +153,7 @@ public void Json_Deserialize() public void Json_Serialize() { // Good - + var snapshot = Blockchain.Singleton.GetSnapshot(); using (var script = new ScriptBuilder()) { script.EmitPush(5); @@ -172,7 +172,7 @@ public void Json_Serialize() script.Emit(OpCode.SETITEM); script.EmitSysCall(InteropService.Json.Serialize); - using (var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, true)) + using (var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true)) { engine.LoadScript(script.ToArray()); From 0a4b436299baaaa4633749c6350a891100fee53c Mon Sep 17 00:00:00 2001 From: bettybao1209 <1062108372@qq.com> Date: Tue, 25 Feb 2020 18:21:42 +0800 Subject: [PATCH 4/6] minor modify --- src/neo/SmartContract/InteropService.cs | 2 +- src/neo/SmartContract/Native/FeeContract.cs | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/neo/SmartContract/InteropService.cs b/src/neo/SmartContract/InteropService.cs index fb6726edf3..c87ad277ea 100644 --- a/src/neo/SmartContract/InteropService.cs +++ b/src/neo/SmartContract/InteropService.cs @@ -7,7 +7,7 @@ namespace Neo.SmartContract { public static partial class InteropService { - public static readonly Dictionary methods = new Dictionary(); + private static readonly Dictionary methods = new Dictionary(); static InteropService() { diff --git a/src/neo/SmartContract/Native/FeeContract.cs b/src/neo/SmartContract/Native/FeeContract.cs index 1cb2e44e12..69e55d7888 100644 --- a/src/neo/SmartContract/Native/FeeContract.cs +++ b/src/neo/SmartContract/Native/FeeContract.cs @@ -22,6 +22,8 @@ public sealed class FeeContract : NativeContract private const byte Prefix_Syscall = 12; private const byte Prefix_OpCode = 13; + private const uint DefaultRatio = 1; + public FeeContract() { Manifest.Features = ContractFeatures.HasStorage; @@ -66,6 +68,7 @@ private StackItem SetSyscallPrice(ApplicationEngine engine, Array args) if (!CheckValidators(engine)) return false; uint method = (uint)((Array)args[0])[0].GetBigInteger(); long value = (long)((Array)args[0])[1].GetBigInteger(); + if (value < 0) return false; StorageKey key = CreateStorageKey(Prefix_Syscall, BitConverter.GetBytes(method)); StorageItem item = engine.Snapshot.Storages.GetAndChange(key, () => new StorageItem()); item.Value = BitConverter.GetBytes(value); @@ -94,6 +97,7 @@ private StackItem SetOpCodePrice(ApplicationEngine engine, Array args) if (!CheckValidators(engine)) return false; uint opCode = (uint)((Array)args[0])[0].GetBigInteger(); long value = (long)((Array)args[0])[1].GetBigInteger(); + if (value < 0) return false; StorageKey key = CreateStorageKey(Prefix_OpCode, BitConverter.GetBytes(opCode)); StorageItem item = engine.Snapshot.Storages.GetAndChange(key, () => new StorageItem()); item.Value = BitConverter.GetBytes(value); @@ -111,7 +115,7 @@ public uint GetRatio(StoreView snapshot) if (snapshot.Storages.TryGet(CreateStorageKey(Prefix_Ratio)) != null) return BitConverter.ToUInt32(snapshot.Storages[CreateStorageKey(Prefix_Ratio)].Value, 0); else - return 1; + return DefaultRatio; } [ContractMethod(0_00030000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })] @@ -119,8 +123,7 @@ private StackItem SetRatio(ApplicationEngine engine, Array args) { if (!CheckValidators(engine)) return false; uint value = (uint)args[0].GetBigInteger(); - if (value == 0) - return false; + if (value == 0) return false; StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Ratio)); storage.Value = BitConverter.GetBytes(value); return true; From 8c074f0388b72bf3860fcbc9898b65141c6014f8 Mon Sep 17 00:00:00 2001 From: bettybao1209 <1062108372@qq.com> Date: Tue, 25 Feb 2020 18:30:21 +0800 Subject: [PATCH 5/6] minor modify --- src/neo/SmartContract/Native/FeeContract.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/FeeContract.cs b/src/neo/SmartContract/Native/FeeContract.cs index 69e55d7888..0af7633bf8 100644 --- a/src/neo/SmartContract/Native/FeeContract.cs +++ b/src/neo/SmartContract/Native/FeeContract.cs @@ -34,7 +34,7 @@ internal override bool Initialize(ApplicationEngine engine) if (!base.Initialize(engine)) return false; engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Ratio), new StorageItem { - Value = BitConverter.GetBytes(1u) + Value = BitConverter.GetBytes(DefaultRatio) }); return true; } From c7706562314c9cace426eef60619f99581a6af50 Mon Sep 17 00:00:00 2001 From: bettybao1209 <1062108372@qq.com> Date: Tue, 25 Feb 2020 18:33:56 +0800 Subject: [PATCH 6/6] format --- tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs index a949fff619..8e60315858 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_FeeContract.cs @@ -65,7 +65,7 @@ public void Check_SetSyscallPrice() ret.ToBoolean().Should().BeFalse(); // With signature - + ret = NativeContract.Fee.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero), "setSyscallPrice", new ContractParameter(ContractParameterType.Array) { Value = values }); ret.Should().BeOfType();