-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Invoke contracts' payable method on asset Transfers #2012
Changes from all commits
7ebddaf
6fe120a
58a7cba
a45d7ef
2e18d11
739aff3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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,39 @@ protected internal void SendNotification(UInt160 hash, string eventName, Array s | |
Notify?.Invoke(this, notification); | ||
notifications ??= new List<NotifyEventArgs>(); | ||
notifications.Add(notification); | ||
|
||
// React to transfer event | ||
|
||
if (eventName == "Transfer") | ||
{ | ||
if (state.Count < 3) throw new ArgumentException("Wrong Transfer definition"); | ||
|
||
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"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One can say that this should be checked by the contract. Though if we're to make sure this is a valid transfer event, maybe it's worth enforcing it here. |
||
|
||
// Validate | ||
|
||
var method = contract.Manifest.Abi.GetMethod("_onPaymentReceived"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. May happen re-entrancy attack?
Then the user's asset can be transfered There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Of course, the users need to be aware and use invocation counter or decrease the balance before send the notification |
||
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 {contract.ScriptHash} From Contract {CurrentScriptHash}"); | ||
|
||
// Call _fallback method | ||
|
||
CallContractInternal(contract, method, new Array(ReferenceCounter) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BTW, this can also prevent some unexpected transfers, like NeoFS contract is happy to accept some GAS, but if you're to throw any NEO at it --- it doesn't know how to handle that, so the contract can check what is being transferred to it and reject things it doesn't expect. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, you can filter with your own code. |
||
{ | ||
CurrentScriptHash.ToArray() /* Token */, | ||
state[0].GetSpan().ToArray() /* From */, | ||
state[2].GetInteger() /* Amount */ | ||
}, | ||
CallFlags.All, CheckReturnType.EnsureIsEmpty); | ||
} | ||
} | ||
|
||
protected internal NotifyEventArgs[] GetNotifications(UInt160 hash) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This in part is #1879, but I don't think we can be that aggressive here without #1883 and checking that the contract in question is NEP-5 compliant in the first place. Otherwise we're reserving this name for NEP-5 contracts only (and there is #1646 for the name also).