[#23] neofs: Implement OnPayment method for asset deposit

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
Alex Vanin 2020-12-09 16:27:39 +03:00 committed by Alex Vanin
parent 3875003b2e
commit 37d8905d55
2 changed files with 40 additions and 15 deletions

View file

@ -4,11 +4,11 @@ events:
- name: Deposit - name: Deposit
parameters: parameters:
- name: from - name: from
type: ByteArray type: Hash160
- name: amount - name: amount
type: Integer type: Integer
- name: receiver - name: receiver
type: ByteArray type: Hash160
- name: txHash - name: txHash
type: Hash256 type: Hash256
- name: Withdraw - name: Withdraw

View file

@ -32,6 +32,7 @@ package smart_contract
*/ */
import ( import (
"github.com/nspcc-dev/neo-go/pkg/interop"
"github.com/nspcc-dev/neo-go/pkg/interop/binary" "github.com/nspcc-dev/neo-go/pkg/interop/binary"
"github.com/nspcc-dev/neo-go/pkg/interop/blockchain" "github.com/nspcc-dev/neo-go/pkg/interop/blockchain"
"github.com/nspcc-dev/neo-go/pkg/interop/contract" "github.com/nspcc-dev/neo-go/pkg/interop/contract"
@ -82,6 +83,9 @@ const (
minInnerRingSize = 3 minInnerRingSize = 3
maxBalanceAmount = 9000 // Max integer of Fixed12 in JSON bound (2**53-1) maxBalanceAmount = 9000 // Max integer of Fixed12 in JSON bound (2**53-1)
// hardcoded value to ignore deposit notification in onReceive
ignoreDepositNotification = "\x57\x0b"
) )
var ( var (
@ -183,7 +187,9 @@ func InnerRingCandidateAdd(key []byte) bool {
to := runtime.GetExecutingScriptHash() to := runtime.GetExecutingScriptHash()
fee := getConfig(ctx, candidateFeeConfigKey).(int) fee := getConfig(ctx, candidateFeeConfigKey).(int)
transferred := contract.Call([]byte(tokenHash), "transfer", from, to, fee, nil).(bool) transferred := contract.Call([]byte(tokenHash),
"transfer", from, to, fee,
[]byte(ignoreDepositNotification)).(bool)
if !transferred { if !transferred {
panic("irCandidateAdd: failed to transfer funds, aborting") panic("irCandidateAdd: failed to transfer funds, aborting")
} }
@ -194,8 +200,34 @@ func InnerRingCandidateAdd(key []byte) bool {
return true return true
} }
// OnPayment is a callback for NEP-17 compatible native GAS contract.
func OnPayment(from interop.Hash160, amount int, data interface{}) {
rcv := data.(interop.Hash160)
if bytesEqual(rcv, []byte(ignoreDepositNotification)) {
return
}
caller := runtime.GetCallingScriptHash()
if !bytesEqual(caller, []byte(tokenHash)) {
panic("onPayment: only GAS can be accepted for deposit")
}
switch len(rcv) {
case 20:
case 0:
rcv = from
default:
panic("onPayment: invalid data argument, expected Hash160")
}
runtime.Log("onPayment: funds have been transferred")
tx := runtime.GetScriptContainer()
runtime.Notify("Deposit", from, amount, rcv, tx.Hash)
}
// Deposit gas assets to this script-hash address in NeoFS balance contract. // Deposit gas assets to this script-hash address in NeoFS balance contract.
func Deposit(from []byte, amount int, rcv []byte) bool { func Deposit(from interop.Hash160, amount int, rcv interop.Hash160) bool {
if !runtime.CheckWitness(from) { if !runtime.CheckWitness(from) {
panic("deposit: you should be the owner of the wallet") panic("deposit: you should be the owner of the wallet")
} }
@ -211,20 +243,12 @@ func Deposit(from []byte, amount int, rcv []byte) bool {
to := runtime.GetExecutingScriptHash() to := runtime.GetExecutingScriptHash()
transferred := contract.Call([]byte(tokenHash), "transfer", from, to, amount, nil).(bool) transferred := contract.Call([]byte(tokenHash), "transfer",
from, to, amount, rcv).(bool)
if !transferred { if !transferred {
panic("deposit: failed to transfer funds, aborting") panic("deposit: failed to transfer funds, aborting")
} }
runtime.Log("deposit: funds have been transferred")
if len(rcv) == 0 {
rcv = from
}
tx := runtime.GetScriptContainer()
runtime.Notify("Deposit", from, amount, rcv, tx.Hash)
return true return true
} }
@ -277,7 +301,8 @@ func Cheque(id, user []byte, amount int, lockAcc []byte) bool {
from := runtime.GetExecutingScriptHash() from := runtime.GetExecutingScriptHash()
transferred := contract.Call([]byte(tokenHash), "transfer", from, user, amount, nil).(bool) transferred := contract.Call([]byte(tokenHash),
"transfer", from, user, amount, nil).(bool)
if !transferred { if !transferred {
panic("cheque: failed to transfer funds, aborting") panic("cheque: failed to transfer funds, aborting")
} }