diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index e0f0db6266..4a047041d2 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -41,6 +41,7 @@ public partial class ApplicationEngine : ExecutionEngine private static IApplicationEngineProvider applicationEngineProvider; private static Dictionary services; private long gas_amount; + private long gas_refuel = 0; private List notifications; private List disposables; private readonly Dictionary invocationCounter = new(); @@ -158,8 +159,12 @@ protected internal void AddGas(long gas) internal void Refuel(long gas) { + if (ScriptContainer is not Transaction tx) throw new InvalidOperationException(); checked { + gas_refuel += gas; + if (gas_refuel > tx.SystemFee + tx.NetworkFee) + throw new InvalidOperationException("Too much GAS is refuelled."); gas_amount += gas; } } diff --git a/src/neo/SmartContract/Native/GasToken.cs b/src/neo/SmartContract/Native/GasToken.cs index 814992f74f..9cfc5c1ede 100644 --- a/src/neo/SmartContract/Native/GasToken.cs +++ b/src/neo/SmartContract/Native/GasToken.cs @@ -40,10 +40,12 @@ internal override async ContractTask OnPersist(ApplicationEngine engine) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] private async ContractTask Refuel(ApplicationEngine engine, UInt160 account, long amount) { - if (amount < 0) throw new ArgumentOutOfRangeException(nameof(amount)); + if (amount <= 0) throw new ArgumentOutOfRangeException(nameof(amount)); + if (ContractManagement.GetContract(engine.Snapshot, engine.CallingScriptHash) is null) + throw new InvalidOperationException(); if (!engine.CheckWitnessInternal(account)) throw new InvalidOperationException(); - await Burn(engine, account, amount); engine.Refuel(amount); + await Burn(engine, account, amount); } } } diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_GasToken.cs b/tests/neo.UnitTests/SmartContract/Native/UT_GasToken.cs index 4bcd2e143f..2107224339 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_GasToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_GasToken.cs @@ -65,7 +65,7 @@ public void Refuel() byte[] script; using (ScriptBuilder sb = new()) { - sb.EmitDynamicCall(NativeContract.GAS.Hash, "refuel", accBalance.ScriptHash, 100 * NativeContract.GAS.Factor); + sb.EmitDynamicCall(NativeContract.GAS.Hash, "refuel", accBalance.ScriptHash, 1 * NativeContract.GAS.Factor); sb.Emit(OpCode.DROP); sb.EmitSysCall(ApplicationEngine.System_Runtime_GasLeft); script = sb.ToArray(); @@ -91,10 +91,10 @@ public void Refuel() engine.LoadScript(tx.Script); Assert.AreEqual(VMState.HALT, engine.Execute()); Assert.AreEqual(1, engine.ResultStack.Count); - Assert.AreEqual(100_00300140, engine.ResultStack.Pop().GetInteger()); + Assert.AreEqual(1_00296140, engine.ResultStack.Pop().GetInteger()); entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState())); - Assert.AreEqual(0, entry.GetInteroperable().Balance); + Assert.AreEqual(99_00000000, entry.GetInteroperable().Balance); } [TestMethod]