From 7ebddafd4dd8b01f382d141f6691d048687302d2 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 21 Oct 2020 16:48:16 +0200 Subject: [PATCH 1/5] React token transfers --- .../ApplicationEngine.Runtime.cs | 33 +++++++++++++++++++ .../SmartContract/Native/Tokens/Nep5Token.cs | 6 ++++ 2 files changed, 39 insertions(+) diff --git a/src/neo/SmartContract/ApplicationEngine.Runtime.cs b/src/neo/SmartContract/ApplicationEngine.Runtime.cs index 674a0cea9e..96a9d59c29 100644 --- a/src/neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/neo/SmartContract/ApplicationEngine.Runtime.cs @@ -1,6 +1,7 @@ using Neo.Cryptography.ECC; using Neo.IO; using Neo.Network.P2P.Payloads; +using Neo.SmartContract.Manifest; using Neo.SmartContract.Native; using Neo.SmartContract.Native.Oracle; using Neo.VM.Types; @@ -187,6 +188,38 @@ protected internal void SendNotification(UInt160 hash, string eventName, Array s Notify?.Invoke(this, notification); notifications ??= new List(); notifications.Add(notification); + + // React to transfer event + + if (eventName == "Transfer") + { + if (state.Count < 3) throw new ArgumentException("Wrong transfer definition"); + + var to = new UInt160(state[1].GetSpan()); + var contract = Snapshot.Contracts.TryGet(to); + if (contract == null) return; + if (!contract.Payable) throw new InvalidOperationException("Not payable contract"); + + // Validate + + var method = contract.Manifest.Abi.GetMethod("_fallback"); + if (method == null) return; + + ContractManifest currentManifest = Snapshot.Contracts.TryGet(CurrentScriptHash)?.Manifest; + if (currentManifest != null && !currentManifest.CanCall(contract.Manifest, method.Name)) + throw new InvalidOperationException($"Cannot Call Method {method} Of Contract {to} From Contract {CurrentScriptHash}"); + + // Call _fallback method + + CallContractInternal(contract, method, + new Array(ReferenceCounter) + { + CurrentScriptHash.ToArray() /* Token */, + state[0].GetSpan().ToArray() /* From */, + state[2].GetInteger() /* Amount */ + }, + CallFlags.None, CheckReturnType.EnsureIsEmpty); + } } protected internal NotifyEventArgs[] GetNotifications(UInt160 hash) diff --git a/src/neo/SmartContract/Native/Tokens/Nep5Token.cs b/src/neo/SmartContract/Native/Tokens/Nep5Token.cs index ed4308b73c..d40526da45 100644 --- a/src/neo/SmartContract/Native/Tokens/Nep5Token.cs +++ b/src/neo/SmartContract/Native/Tokens/Nep5Token.cs @@ -89,6 +89,12 @@ internal protected virtual void Burn(ApplicationEngine engine, UInt160 account, engine.SendNotification(Hash, "Transfer", new Array { account.ToArray(), StackItem.Null, amount }); } + [ContractMethod(0_01000000, CallFlags.AllowStates, Name = "_fallback")] + public virtual void OnFallback(UInt160 token, UInt160 from, BigInteger amount) + { + throw new InvalidOperationException(); + } + [ContractMethod(0_01000000, CallFlags.AllowStates)] public virtual BigInteger TotalSupply(StoreView snapshot) { From 6fe120a94d763606f5055b4ca645371611ee5e9e Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 21 Oct 2020 16:53:00 +0200 Subject: [PATCH 2/5] Change to all --- src/neo/SmartContract/ApplicationEngine.Runtime.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Runtime.cs b/src/neo/SmartContract/ApplicationEngine.Runtime.cs index 96a9d59c29..7e1a1b8f1a 100644 --- a/src/neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/neo/SmartContract/ApplicationEngine.Runtime.cs @@ -218,7 +218,7 @@ protected internal void SendNotification(UInt160 hash, string eventName, Array s state[0].GetSpan().ToArray() /* From */, state[2].GetInteger() /* Amount */ }, - CallFlags.None, CheckReturnType.EnsureIsEmpty); + CallFlags.All, CheckReturnType.EnsureIsEmpty); } } From 58a7cba3856aa81d988f96d0785b06b4969884ab Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 21 Oct 2020 16:55:08 +0200 Subject: [PATCH 3/5] Remove NEP5 changes because is not payable --- src/neo/SmartContract/Native/Tokens/Nep5Token.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/Nep5Token.cs b/src/neo/SmartContract/Native/Tokens/Nep5Token.cs index d40526da45..ed4308b73c 100644 --- a/src/neo/SmartContract/Native/Tokens/Nep5Token.cs +++ b/src/neo/SmartContract/Native/Tokens/Nep5Token.cs @@ -89,12 +89,6 @@ internal protected virtual void Burn(ApplicationEngine engine, UInt160 account, engine.SendNotification(Hash, "Transfer", new Array { account.ToArray(), StackItem.Null, amount }); } - [ContractMethod(0_01000000, CallFlags.AllowStates, Name = "_fallback")] - public virtual void OnFallback(UInt160 token, UInt160 from, BigInteger amount) - { - throw new InvalidOperationException(); - } - [ContractMethod(0_01000000, CallFlags.AllowStates)] public virtual BigInteger TotalSupply(StoreView snapshot) { From a45d7efac3e1ef146d7792df6c89ffa2fec83946 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 21 Oct 2020 16:58:26 +0200 Subject: [PATCH 4/5] Clean code --- src/neo/SmartContract/ApplicationEngine.Runtime.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Runtime.cs b/src/neo/SmartContract/ApplicationEngine.Runtime.cs index 7e1a1b8f1a..cfd8967bb0 100644 --- a/src/neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/neo/SmartContract/ApplicationEngine.Runtime.cs @@ -193,10 +193,12 @@ protected internal void SendNotification(UInt160 hash, string eventName, Array s if (eventName == "Transfer") { - if (state.Count < 3) throw new ArgumentException("Wrong transfer definition"); + if (state.Count < 3) throw new ArgumentException("Wrong Transfer definition"); - var to = new UInt160(state[1].GetSpan()); - var contract = Snapshot.Contracts.TryGet(to); + var to = state[1].GetSpan(); + if (to.Length != UInt160.Length) throw new ArgumentException("Wrong Transfer definition"); + + var contract = Snapshot.Contracts.TryGet(new UInt160(to)); if (contract == null) return; if (!contract.Payable) throw new InvalidOperationException("Not payable contract"); @@ -207,12 +209,11 @@ protected internal void SendNotification(UInt160 hash, string eventName, Array s ContractManifest currentManifest = Snapshot.Contracts.TryGet(CurrentScriptHash)?.Manifest; if (currentManifest != null && !currentManifest.CanCall(contract.Manifest, method.Name)) - throw new InvalidOperationException($"Cannot Call Method {method} Of Contract {to} From Contract {CurrentScriptHash}"); + throw new InvalidOperationException($"Cannot Call Method {method} Of Contract {contract.ScriptHash} From Contract {CurrentScriptHash}"); // Call _fallback method - CallContractInternal(contract, method, - new Array(ReferenceCounter) + CallContractInternal(contract, method, new Array(ReferenceCounter) { CurrentScriptHash.ToArray() /* Token */, state[0].GetSpan().ToArray() /* From */, From 2e18d118866a0fa14789b4e0c3ec1f7cb899aff4 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 22 Oct 2020 09:37:59 +0200 Subject: [PATCH 5/5] Rename --- src/neo/SmartContract/ApplicationEngine.Runtime.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Runtime.cs b/src/neo/SmartContract/ApplicationEngine.Runtime.cs index cfd8967bb0..5c8f1dc79c 100644 --- a/src/neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/neo/SmartContract/ApplicationEngine.Runtime.cs @@ -204,7 +204,7 @@ protected internal void SendNotification(UInt160 hash, string eventName, Array s // Validate - var method = contract.Manifest.Abi.GetMethod("_fallback"); + var method = contract.Manifest.Abi.GetMethod("_onPaymentReceived"); if (method == null) return; ContractManifest currentManifest = Snapshot.Contracts.TryGet(CurrentScriptHash)?.Manifest;