diff --git a/cli/testdata/verify.go b/cli/testdata/verify.go index 6a3ed7b6a..4abc927d5 100644 --- a/cli/testdata/verify.go +++ b/cli/testdata/verify.go @@ -4,5 +4,5 @@ func Verify() bool { return true } -func OnPayment(from []byte, amount int, data interface{}) { +func OnNEP17Payment(from []byte, amount int, data interface{}) { } diff --git a/cli/testdata/verify.manifest.json b/cli/testdata/verify.manifest.json index 103a744a8..47bf7b91a 100755 --- a/cli/testdata/verify.manifest.json +++ b/cli/testdata/verify.manifest.json @@ -1 +1 @@ -{"name":"verify","abi":{"methods":[{"name":"verify","offset":0,"parameters":[],"returntype":"Boolean","safe":false},{"name":"onPayment","offset":5,"parameters":[{"name":"from","type":"ByteArray"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Void","safe":false}],"events":[{"name":"Hello world!","parameters":[{"name":"args","type":"Array"}]}]},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"extra":null} \ No newline at end of file +{"name":"verify","abi":{"methods":[{"name":"verify","offset":0,"parameters":[],"returntype":"Boolean","safe":false},{"name":"onNEP17Payment","offset":5,"parameters":[{"name":"from","type":"ByteArray"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Void","safe":false}],"events":[{"name":"Hello world!","parameters":[{"name":"args","type":"Array"}]}]},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"extra":null} diff --git a/pkg/core/interop_system_test.go b/pkg/core/interop_system_test.go index 9f5098ffb..7bbe96958 100644 --- a/pkg/core/interop_system_test.go +++ b/pkg/core/interop_system_test.go @@ -340,13 +340,20 @@ func getTestContractState(bc *Blockchain) (*state.Contract, *state.Contract) { emit.Syscall(w.BinWriter, interopnames.SystemStorageGetContext) emit.Syscall(w.BinWriter, interopnames.SystemStorageGet) emit.Opcodes(w.BinWriter, opcode.RET) - onPaymentOff := w.Len() + onNEP17PaymentOff := w.Len() emit.Syscall(w.BinWriter, interopnames.SystemRuntimeGetCallingScriptHash) emit.Int(w.BinWriter, 4) emit.Opcodes(w.BinWriter, opcode.PACK) emit.String(w.BinWriter, "LastPayment") emit.Syscall(w.BinWriter, interopnames.SystemRuntimeNotify) emit.Opcodes(w.BinWriter, opcode.RET) + onNEP11PaymentOff := w.Len() + emit.Syscall(w.BinWriter, interopnames.SystemRuntimeGetCallingScriptHash) + emit.Int(w.BinWriter, 4) + emit.Opcodes(w.BinWriter, opcode.PACK) + emit.String(w.BinWriter, "LostPayment") + emit.Syscall(w.BinWriter, interopnames.SystemRuntimeNotify) + emit.Opcodes(w.BinWriter, opcode.RET) update3Off := w.Len() emit.Int(w.BinWriter, 3) emit.Opcodes(w.BinWriter, opcode.JMP, 2+1) @@ -456,8 +463,18 @@ func getTestContractState(bc *Blockchain) (*state.Contract, *state.Contract) { ReturnType: smartcontract.VoidType, }, { - Name: "onPayment", - Offset: onPaymentOff, + Name: manifest.MethodOnNEP11Payment, + Offset: onNEP11PaymentOff, + Parameters: []manifest.Parameter{ + manifest.NewParameter("from", smartcontract.Hash160Type), + manifest.NewParameter("amount", smartcontract.IntegerType), + manifest.NewParameter("tokenid", smartcontract.ByteArrayType), + }, + ReturnType: smartcontract.VoidType, + }, + { + Name: manifest.MethodOnNEP17Payment, + Offset: onNEP17PaymentOff, Parameters: []manifest.Parameter{ manifest.NewParameter("from", smartcontract.Hash160Type), manifest.NewParameter("amount", smartcontract.IntegerType), diff --git a/pkg/core/native/native_nep17.go b/pkg/core/native/native_nep17.go index 7ba55dd6c..ca092bd8b 100644 --- a/pkg/core/native/native_nep17.go +++ b/pkg/core/native/native_nep17.go @@ -143,7 +143,7 @@ func (c *nep17TokenNative) postTransfer(ic *interop.Context, from, to *util.Uint stackitem.NewBigInteger(amount), data, } - if err := contract.CallFromNative(ic, c.Hash, cs, manifest.MethodOnPayment, args, false); err != nil { + if err := contract.CallFromNative(ic, c.Hash, cs, manifest.MethodOnNEP17Payment, args, false); err != nil { panic(err) } } diff --git a/pkg/core/native/nonfungible.go b/pkg/core/native/nonfungible.go index ba0d3e4b2..dd31eeafa 100644 --- a/pkg/core/native/nonfungible.go +++ b/pkg/core/native/nonfungible.go @@ -8,6 +8,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/dao" "github.com/nspcc-dev/neo-go/pkg/core/interop" + "github.com/nspcc-dev/neo-go/pkg/core/interop/contract" "github.com/nspcc-dev/neo-go/pkg/core/interop/runtime" istorage "github.com/nspcc-dev/neo-go/pkg/core/interop/storage" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -280,6 +281,26 @@ func (n *nonfungible) postTransfer(ic *interop.Context, from, to *util.Uint160, }), } ic.Notifications = append(ic.Notifications, ne) + if to == nil { + return + } + cs, err := ic.GetContract(*to) + if err != nil { + return + } + + fromArg := stackitem.Item(stackitem.Null{}) + if from != nil { + fromArg = stackitem.NewByteArray((*from).BytesBE()) + } + args := []stackitem.Item{ + fromArg, + stackitem.NewBigInteger(intOne), + stackitem.NewByteArray(tokenID), + } + if err := contract.CallFromNative(ic, n.Hash, cs, manifest.MethodOnNEP11Payment, args, false); err != nil { + panic(err) + } } func (n *nonfungible) burn(ic *interop.Context, tokenID []byte) { diff --git a/pkg/core/native/notary.go b/pkg/core/native/notary.go index 9713ba4ca..bcbdf6867 100644 --- a/pkg/core/native/notary.go +++ b/pkg/core/native/notary.go @@ -55,7 +55,7 @@ var maxNotValidBeforeDeltaKey = []byte{10} func newNotary() *Notary { n := &Notary{ContractMD: *interop.NewContractMD(nativenames.Notary, notaryContractID)} - desc := newDescriptor("onPayment", smartcontract.VoidType, + desc := newDescriptor("onNEP17Payment", smartcontract.VoidType, manifest.NewParameter("from", smartcontract.Hash160Type), manifest.NewParameter("amount", smartcontract.IntegerType), manifest.NewParameter("data", smartcontract.AnyType)) diff --git a/pkg/core/native_name_service_test.go b/pkg/core/native_name_service_test.go index 2042ee55a..1ffd822e4 100644 --- a/pkg/core/native_name_service_test.go +++ b/pkg/core/native_name_service_test.go @@ -287,6 +287,16 @@ func TestTransfer(t *testing.T) { testNameServiceInvokeAux(t, bc, defaultNameServiceSysfee, from, "totalSupply", 1) testNameServiceInvokeAux(t, bc, defaultNameServiceSysfee, from, "ownerOf", to.Contract.ScriptHash().BytesBE(), []byte("neo.com")) + cs, cs2 := getTestContractState(bc) // cs2 doesn't have OnNEP11Transfer + require.NoError(t, bc.contracts.Management.PutContractState(bc.dao, cs)) + require.NoError(t, bc.contracts.Management.PutContractState(bc.dao, cs2)) + testNameServiceInvokeAux(t, bc, defaultRegisterSysfee, to, "transfer", + nil, cs2.Hash.BytesBE(), []byte("neo.com")) + testNameServiceInvokeAux(t, bc, defaultRegisterSysfee, to, "transfer", + true, cs.Hash.BytesBE(), []byte("neo.com")) + testNameServiceInvokeAux(t, bc, defaultNameServiceSysfee, from, "totalSupply", 1) + testNameServiceInvokeAux(t, bc, defaultNameServiceSysfee, from, "ownerOf", + cs.Hash.BytesBE(), []byte("neo.com")) } func TestTokensOf(t *testing.T) { diff --git a/pkg/smartcontract/manifest/manifest.go b/pkg/smartcontract/manifest/manifest.go index e65175e85..b622ab33d 100644 --- a/pkg/smartcontract/manifest/manifest.go +++ b/pkg/smartcontract/manifest/manifest.go @@ -21,8 +21,11 @@ const ( // MethodVerify is a name for default verification method. MethodVerify = "verify" - // MethodOnPayment is name of the method which is called when contract receives funds. - MethodOnPayment = "onPayment" + // MethodOnNEP17Payment is name of the method which is called when contract receives NEP-17 tokens. + MethodOnNEP17Payment = "onNEP17Payment" + + // MethodOnNEP11Payment is the name of the method which is called when contract receives NEP-11 tokens. + MethodOnNEP11Payment = "onNEP11Payment" // NEP10StandardName represents the name of NEP10 smartcontract standard. NEP10StandardName = "NEP-10"