From fdb6e9fa8b1b2597a02f5a06215f9322ebc5acfe Mon Sep 17 00:00:00 2001 From: Vladimir Domnich Date: Mon, 20 Nov 2023 16:05:27 +0400 Subject: [PATCH] Fix buying items from merchants Signed-off-by: Vladimir Domnich --- l6/README.md | 4 ++++ l6/merchant/config.yml | 2 +- l6/merchant/merchant_contract.go | 15 ++++++++++++++- l6/player/player_contract.go | 17 ++++++++++++++++- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/l6/README.md b/l6/README.md index e93b5b0..1bb0f78 100644 --- a/l6/README.md +++ b/l6/README.md @@ -99,3 +99,7 @@ To create a new player, invoke `newPlayer` function on the player contract and s neo-go contract invokefunction -r http://localhost:30333 -w ../../wallet.json e7e4910b3a83ce0eff180a3f5462030391fde830 newPlayer string:demo ``` +```sh +neo-go contract invokefunction -r http://localhost:30333 -w ../../wallet.json 8d099cb315c03c1f040d8912f1f2a84e569ca50c buyItem string:demo string:Shortbow -- 'NP8wjGz3Wvxe4gUAkTbK2McR95Y4LM2jMW:None' +``` + diff --git a/l6/merchant/config.yml b/l6/merchant/config.yml index b032344..ed61056 100644 --- a/l6/merchant/config.yml +++ b/l6/merchant/config.yml @@ -1,6 +1,6 @@ name: "Merchant" supportedstandards: [] events: -safemethods: ["getItemName"] +safemethods: ["getItemName", "getLotsForSale"] permissions: - methods: ["onNEP17Payment", "transfer"] diff --git a/l6/merchant/merchant_contract.go b/l6/merchant/merchant_contract.go index d952168..76e6b95 100644 --- a/l6/merchant/merchant_contract.go +++ b/l6/merchant/merchant_contract.go @@ -2,6 +2,7 @@ package player import ( "github.com/nspcc-dev/neo-go/pkg/interop" + "github.com/nspcc-dev/neo-go/pkg/interop/iterator" "github.com/nspcc-dev/neo-go/pkg/interop/native/gas" "github.com/nspcc-dev/neo-go/pkg/interop/native/std" "github.com/nspcc-dev/neo-go/pkg/interop/runtime" @@ -47,6 +48,18 @@ func GetItemName(lotID int) string { return getLot(storage.GetReadOnlyContext(), lotID).itemName } +func GetLotsForSale() []Lot { + lots := make([]Lot, 0) + + ctx := storage.GetReadOnlyContext() + it := storage.Find(ctx, lotsPrefix, storage.ValuesOnly|storage.DeserializeValues) + for iterator.Next(it) { + lot := iterator.Value(it).(Lot) + lots = append(lots, lot) + } + return lots +} + func Sell(itemName string, price int) { ctx := storage.GetContext() playerHash := storage.Get(ctx, playerHashKey).(interop.Hash160) @@ -63,7 +76,7 @@ func Sell(itemName string, price int) { gasAmount := price * gasDecimals success := gas.Transfer(runtime.GetExecutingScriptHash(), runtime.GetScriptContainer().Sender, gasAmount, nil) if !success { - panic("failed to transfer gas") + panic("failed to transfer gas to seller") } } diff --git a/l6/player/player_contract.go b/l6/player/player_contract.go index 7c2fee5..0f36e34 100644 --- a/l6/player/player_contract.go +++ b/l6/player/player_contract.go @@ -7,8 +7,11 @@ import ( "github.com/nspcc-dev/neo-go/pkg/interop/native/std" "github.com/nspcc-dev/neo-go/pkg/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/interop/storage" + "github.com/nspcc-dev/neo-go/pkg/interop/util" ) +const gasDecimals = 1_0000_0000 + var itemPrices = map[string]int{ "Sword": 100, "Shortbow": 50, @@ -94,7 +97,11 @@ func BuyItemForGas(playerName string, lotID int, itemPrice int, merchantHash int itemName := contract.Call(merchantHash, "getItemName", contract.ReadOnly, lotID).(string) - gas.Transfer(runtime.GetScriptContainer().Sender, merchantHash, itemPrice, lotID) + gasPrice := itemPrice * gasDecimals + success := gas.Transfer(runtime.GetScriptContainer().Sender, merchantHash, gasPrice, lotID) + if !success { + panic("failed to transfer gas to merchant") + } addItemToInventory(player, itemName) savePlayer(ctx, playerName, player) @@ -112,7 +119,15 @@ func SellItemForGas(playerName string, itemName string, itemPrice int, merchantH } removeItemFromInventory(player, itemName) + balanceBefore := gas.BalanceOf(runtime.GetScriptContainer().Sender) contract.Call(merchantHash, "sell", contract.All, itemName, itemPrice) + balanceAfter := gas.BalanceOf(runtime.GetScriptContainer().Sender) + + gasProfit := (balanceAfter - balanceBefore) + if gasProfit < itemPrice*gasDecimals { + runtime.Log("merchant payment does not cover item price: " + std.Itoa10(gasProfit) + " < " + std.Itoa10(itemPrice*gasDecimals)) + util.Abort() + } savePlayer(ctx, playerName, player) }