1

I think the answer has something to do with giving the contract eosio.code authority:

// example lets foo's contract have foo@active authority:

cleos set account permission foo active '{"threshold": 1, "keys": [{"key": "public-key-here","weight": 1}],"accounts": [{"permission":{"actor":"foo","permission":"eosio.code"},"weight":1}]}' owner -p foo@active')

Link: https://trybe.one/the-ultimate-end-to-end-eos-dapp-tutorial-part-2/

I am on the last step:

# Buy product from Marketplace
cleos push action market buy '["wade",1]' -p wade

Instead of getting the expected response, I get the following from cleos:

enter image description here

As well as the following in nodeos:

enter image description here

To remedy this, I tried with -p wade, -p wade@active, -p wade@owner, and yet I still receive the same message. I tried the getplayer command using wade's permission to ensure that my wallet was passing keys appropriately.

After this, I deleted the chain and re added all of the users, their abilities, and the currency. When I came to this last command, I received the same response.

The asset and action pieces in the buy function may be throwing it off somehow. In the tutorial the account anorak has 2 contracts pushed to it. It appears that when the other is pushed, the other no longer responds. I've tried pushing the action with either contract being loaded which produces the same error.


Function:

void Marketplace::buy(account_name buyer, uint64_t productId) {
    productIndex products(_self, _self);

    auto iterator = products.find(productId);
    eosio_assert(iterator != products.end(), "The product not found");

    auto product = products.get(productId);
    eosio_assert(product.quantity > 0, "The product is out of stock");

    //Create asset
    //asset({amount}, string_to_symbol({precision}, {symbol}));
    asset productPrice = asset(product.price, string_to_symbol(4, "OAS"));

    // Do inline trasfer
    // action({permission_level}, {contract_deployer}, {contract_action}, {data_to_pass}).send();
    action(vector<permission_level>(), N(anorak), N(transfer), make_tuple(buyer, _self, productPrice, string(""))).send();

    // Execute action from another contract
    // action({permission_level}, {contract_deployer}, {contract_action}, {data_to_pass}).send();
    action(vector<permission_level>(), N(anorak), N(additem), make_tuple(buyer,
                                                                             product.product_id,
                                                                             product.name,
                                                                             product.power,
                                                                             product.health,
                                                                             product.ability,
                                                                             product.level_up
    )).send();

    update(buyer, product.product_id, -1);
}

Marketplace.hpp:

#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>
#include <eosiolib/asset.hpp>
#include <string>

namespace Oasis {
    using namespace eosio;
    using std::string;

    class Marketplace : public contract {
        using contract::contract;

    public:

        void buy(account_name buyer, uint64_t productId);

        //@abi action
        void getbyid(uint64_t productId);

        /**
         * Marketplace processes
        */

        //@abi table product i64
        struct product {
            uint64_t product_id;
            string name;
            uint64_t power;
            uint64_t health;
            string ability;
            uint64_t level_up;
            uint64_t quantity;
            uint64_t price;

            uint64_t primary_key() const { return product_id; }

            EOSLIB_SERIALIZE(product,
                    (product_id)
                    (name)
                    (power)(health)
                    (ability)
                    (level_up)
                    (quantity)
                    (price)
        )};

        typedef multi_index<N(product), product> productIndex;

        //@abi action
        void add(account_name account, product newProduct);

        //@abi action
        void update(account_name account, uint64_t product_id, uint64_t quantity);

        //@abi action
        void remove(account_name account, uint64_t productId);
    };

    EOSIO_ABI(Marketplace, (buy)(getbyid)(add)(update)(remove));
}

Marketplace.cpp:

#include "Marketplace.hpp"

namespace Oasis{
    void Marketplace::buy(account_name buyer, uint64_t productId) {
        productIndex products(_self, _self);

        auto iterator = products.find(productId);
        eosio_assert(iterator != products.end(), "The product not found");

        auto product = products.get(productId);
        eosio_assert(product.quantity > 0, "The product is out of stock");

        asset productPrice = asset(product.price, string_to_symbol(4, "OAS"));

        action(vector<permission_level>(), N(anorak), N(transfer), make_tuple(buyer, _self, productPrice, string(""))).send();

        action(vector<permission_level>(), N(anorak), N(additem), make_tuple(buyer,
                                                                             product.product_id,
                                                                             product.name,
                                                                             product.power,
                                                                             product.health,
                                                                             product.ability,
                                                                             product.level_up
        )).send();

        update(buyer, product.product_id, -1);
    }

    void Marketplace::getbyid(uint64_t productId) {
        productIndex products(_self, _self);

        auto iterator = products.find(productId);
        eosio_assert(iterator != products.end(), "Product not found");

        auto product = products.get(productId);
        print("Id: ", product.product_id);
        print(" | Name: ", product.name.c_str());
        print(" | Power: ", product.power);
        print(" | Health: ", product.health);
        print(" | Ability: ", product.ability.c_str());
        print(" | Level up: ", product.level_up);
        print(" | Quantity: ", product.quantity);
        print(" | Price: ", product.price);
    }

    void Marketplace::add(account_name account, product newProduct) {
        require_auth(account);

        productIndex products(_self, _self);

        auto iterator = products.find(newProduct.product_id);
        eosio_assert(iterator == products.end(), "Product for this ID already exists");

        products.emplace(account, [&](auto& product) {
            product.product_id = newProduct.product_id;
            product.name = newProduct.name;
            product.power = newProduct.power;
            product.health = newProduct.health;
            product.ability = newProduct.ability;
            product.level_up = newProduct.level_up;
            product.quantity = newProduct.quantity;
            product.price = newProduct.price;
        });
    }

    void Marketplace::update(account_name account, uint64_t product_id, uint64_t quantity) {
        require_auth(account);

        productIndex products(_self, _self);

        auto iterator = products.find(product_id);
        eosio_assert(iterator != products.end(), "Product not found");

        products.modify(iterator, account, [&](auto& product) {
            product.quantity += quantity;
        });
    }

    void Marketplace::remove(account_name account, uint64_t productId) {
        require_auth(account);

        productIndex products(_self, _self);

        auto iterator = products.find(productId);
        eosio_assert(iterator != products.end(), "Product not found");

        products.erase(iterator);
    }
}

Players.hpp

#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>
#include <string>

namespace Oasis {
    using namespace eosio;
    using std::string;

    class Players : public contract {
        using contract::contract;

    public:

        Players(account_name self):contract(self) {}

        //@abi table item i64
        struct item {
            uint64_t item_id;
            string name;
            uint64_t power;
            uint64_t health;
            string ability;
            uint64_t level_up;

            uint64_t primary_key() const { return item_id; }

            EOSLIB_SERIALIZE(item, (item_id)(name)(power)(health)(ability)(level_up))
        };

        //@abi action
        void add(account_name account, string& username);

        //@abi action
        void update(account_name account, uint64_t level, int64_t healthPoints, int64_t energyPoints);

        //@abi action
        void getplayer(const account_name account);

        //@abi action
        void addability(const account_name account, string& ability);

        //@abi action
        void additem(const account_name account, item purchased_item);

        //@abi table player i64
        struct player {
            uint64_t account_name;
            string username;
            uint64_t level;
            int64_t health_points = 1000;
            int64_t energy_points = 1000;
            vector<string> abilities; // This is our new property
            vector<item> inventory;

            uint64_t primary_key() const { return account_name; }

            EOSLIB_SERIALIZE(player,
                    (account_name)
                    (username)
                    (level)
                    (health_points)
                    (energy_points)
                    (abilities)
                    (inventory)
        )};

        typedef multi_index<N(player), player> playerIndex;
    };

    EOSIO_ABI(Players, (add)(update)(getplayer)(addability)(additem));
}

Players.cpp

#include "Players.hpp"

namespace Oasis{

    void Players::add(account_name account, string& username){

        require_auth(account);

        playerIndex players(_self, _self);

        auto iterator = players.find(account);
        eosio_assert(iterator == players.end(), "Address for account already exists");

        players.emplace(account, [&](auto& player) {
            player.account_name = account;
            player.username = username;
            player.level = 1;
            player.health_points = 1000;
            player.energy_points = 1000;
        });

    }

    void Players::update(account_name account,
                         uint64_t level,
                         int64_t healthPoints,
                         int64_t energyPoints){

        require_auth(account);

        playerIndex players (_self, _self);

        auto iterator = players.find(account);
        eosio_assert(iterator != players.end(), "Address for account not found");

        players.modify(iterator, account, [&](auto& player) {
            player.level = level;
            if ((player.health_points - healthPoints) < 0) {
                player.health_points = 0;
            } else {
                player.health_points -= healthPoints;
            }

            if ((player.energy_points - energyPoints) < 0){
                player.energy_points = 0;
            } else {
                player.energy_points -= energyPoints;
            }
        });
    }

    void Players::getplayer(const account_name account){
        require_auth(account);

        playerIndex players (_self, _self);

        auto iterator = players.find(account);
        eosio_assert(iterator != players.end(), "Address for account not found");

        auto currentPlayer = players.get(account);

        print("Username: ", currentPlayer.username.c_str());
        print(" Level: ", currentPlayer.level);
        print(" Health: ", currentPlayer.health_points);
        print(" Energy: ", currentPlayer.energy_points);

        if (currentPlayer.abilities.size() > 0) {
            print(" Abilities: ");

            for (uint32_t i = 0; i < currentPlayer.abilities.size(); i++) {
                print(currentPlayer.abilities.at(i).c_str(), " ");
            }
        } else {
            print(" No Abilities");
        }
        if (currentPlayer.inventory.size() > 0) {
            print(" Items: ");

            for (uint32_t i = 0; i < currentPlayer.inventory.size(); i++) {
                item currentItem = currentPlayer.inventory.at(i);
                print(currentItem.name.c_str(), " == ");
            }
        } else {
            print(" Empty inventory");
        }
    }

    void Players::addability(const account_name account, string& ability) {
        require_auth(account);

        playerIndex players(_self, _self);

        auto iterator = players.find(account);
        eosio_assert(iterator != players.end(), "Address for account not found");

        players.modify(iterator, account, [&](auto& player) {
            player.abilities.push_back(ability);
        });
    }

    void Players::additem(const account_name account, item purchased_item) {
        playerIndex players(_self, _self);

        auto iterator = players.find(account);
        eosio_assert(iterator != players.end(), "Address for account not found");

        players.modify(iterator, account, [&](auto& player) {
            player.energy_points += purchased_item.power;
            player.health_points += purchased_item.health;
            player.level += purchased_item.level_up;
            player.abilities.push_back(purchased_item.ability);
            player.inventory.push_back(item{
                    purchased_item.item_id,
                    purchased_item.name,
                    purchased_item.power,
                    purchased_item.health,
                    purchased_item.ability,
                    purchased_item.level_up
            });
        });

        print("Item Id: ", purchased_item.item_id);
        print(" | Name: ", purchased_item.name.c_str());
        print(" | Power: ", purchased_item.power);
        print(" | Health: ", purchased_item.health);
        print(" | Ability: ", purchased_item.ability.c_str());
        print(" | Level up: ", purchased_item.level_up);
    }
}

Error from trying smarteasy's post:

enter image description here

Complete Request/Response from eos:

cleos --print-request --print-response push action market buy '["wade",1]' -p wade

REQUEST:
---------------------
POST /v1/chain/abi_json_to_bin HTTP/1.0
Host: localhost
content-length: 76
Accept: */*
Connection: close

{
  "code": "market",
  "action": "buy",
  "args": [
    "wade",
    1
  ]
}
---------------------
RESPONSE:
---------------------
{
  "binargs": "0000000000a092e10100000000000000"
}
---------------------
REQUEST:
---------------------
POST /v1/chain/get_info HTTP/1.0
Host: localhost
content-length: 0
Accept: */*
Connection: close


---------------------
RESPONSE:
---------------------
{
  "server_version": "90fefdd1",
  "chain_id": "cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f",
  "head_block_num": 73808,
  "last_irreversible_block_num": 73807,
  "last_irreversible_block_id": "0001204fe7301c470bf0f59ceb5199fca2032fa3f5c6b12fd7517e0bb100391d",
  "head_block_id": "000120507f2a52644b3238ed7d8cf50b7146d66cd84dbf8f8f1ffdcddf3e1f83",
  "head_block_time": "2018-07-04T12:49:01.500",
  "head_block_producer": "eosio",
  "virtual_block_cpu_limit": 200000000,
  "virtual_block_net_limit": 1048576000,
  "block_cpu_limit": 199900,
  "block_net_limit": 1048576
}
---------------------
REQUEST:
---------------------
POST /v1/wallet/get_public_keys HTTP/1.0
Host: localhost
content-length: 0
Accept: */*
Connection: close


---------------------
RESPONSE:
---------------------
[
  "EOS59BLH6u4DgQiNiTQXYX1a1sycpJA8sDsF7Dw5h819sKntWmwuL",
  "EOS5FGitT7YF1pEAo5fGoiJxWbQDmM4771bD3e5d884qxf9KcWym2",
  "EOS5bTVMPvkvG3xJsn7vMKvB7BcHpcoMpG34YnYNA3eUXQt211r9m",
  "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
  "EOS7GCBtiyh4Kfk6NHwLJ5xhyxgzg7RYVwvcVaHD8NDHWp4HDVddC",
  "EOS8A5pNg33MUN4EKb7LdA1d6yv6vcc1Ujhh92bQz2q5fXgBG61bt",
  "EOS8SWeZ9WGyMZbYTi7sTLZRS5LRSKt93KN1KCPr2xbLnZ1sa7jsZ"
]
---------------------
REQUEST:
---------------------
POST /v1/chain/get_required_keys HTTP/1.0
Host: localhost
content-length: 976
Accept: */*
Connection: close

{
  "transaction": {
    "expiration": "2018-07-04T12:49:31",
    "ref_block_num": 8271,
    "ref_block_prefix": 2633363467,
    "max_net_usage_words": 0,
    "max_cpu_usage_ms": 0,
    "delay_sec": 0,
    "context_free_actions": [],
    "actions": [{
        "account": "market",
        "name": "buy",
        "authorization": [{
            "actor": "wade",
            "permission": "active"
          }
        ],
        "data": "0000000000a092e10100000000000000"
      }
    ],
    "transaction_extensions": []
  },
  "available_keys": [
    "EOS59BLH6u4DgQiNiTQXYX1a1sycpJA8sDsF7Dw5h819sKntWmwuL",
    "EOS5FGitT7YF1pEAo5fGoiJxWbQDmM4771bD3e5d884qxf9KcWym2",
    "EOS5bTVMPvkvG3xJsn7vMKvB7BcHpcoMpG34YnYNA3eUXQt211r9m",
    "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
    "EOS7GCBtiyh4Kfk6NHwLJ5xhyxgzg7RYVwvcVaHD8NDHWp4HDVddC",
    "EOS8A5pNg33MUN4EKb7LdA1d6yv6vcc1Ujhh92bQz2q5fXgBG61bt",
    "EOS8SWeZ9WGyMZbYTi7sTLZRS5LRSKt93KN1KCPr2xbLnZ1sa7jsZ"
  ]
}
---------------------
RESPONSE:
---------------------
{
  "required_keys": [
    "EOS8SWeZ9WGyMZbYTi7sTLZRS5LRSKt93KN1KCPr2xbLnZ1sa7jsZ"
  ]
}
---------------------
REQUEST:
---------------------
POST /v1/wallet/sign_transaction HTTP/1.0
Host: localhost
content-length: 692
Accept: */*
Connection: close

[{
    "expiration": "2018-07-04T12:49:31",
    "ref_block_num": 8271,
    "ref_block_prefix": 2633363467,
    "max_net_usage_words": 0,
    "max_cpu_usage_ms": 0,
    "delay_sec": 0,
    "context_free_actions": [],
    "actions": [{
        "account": "market",
        "name": "buy",
        "authorization": [{
            "actor": "wade",
            "permission": "active"
          }
        ],
        "data": "0000000000a092e10100000000000000"
      }
    ],
    "transaction_extensions": [],
    "signatures": [],
    "context_free_data": []
  },[
    "EOS8SWeZ9WGyMZbYTi7sTLZRS5LRSKt93KN1KCPr2xbLnZ1sa7jsZ"
  ],
  "cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f"
]
---------------------
RESPONSE:
---------------------
{
  "expiration": "2018-07-04T12:49:31",
  "ref_block_num": 8271,
  "ref_block_prefix": 2633363467,
  "max_net_usage_words": 0,
  "max_cpu_usage_ms": 0,
  "delay_sec": 0,
  "context_free_actions": [],
  "actions": [{
      "account": "market",
      "name": "buy",
      "authorization": [{
          "actor": "wade",
          "permission": "active"
        }
      ],
      "data": "0000000000a092e10100000000000000"
    }
  ],
  "transaction_extensions": [],
  "signatures": [
    "SIG_K1_K2CFA5n2wQXuGdeVEdWcpBDhAZk7Ryb2q9PgVFep6UDYydRejKikmZmgembvDs1AX6JCH2xbSvsdttGk8x3nNY9ybc7LDa"
  ],
  "context_free_data": []
}
---------------------
REQUEST:
---------------------
POST /v1/chain/push_transaction HTTP/1.0
Host: localhost
content-length: 344
Accept: */*
Connection: close

{
  "signatures": [
    "SIG_K1_K2CFA5n2wQXuGdeVEdWcpBDhAZk7Ryb2q9PgVFep6UDYydRejKikmZmgembvDs1AX6JCH2xbSvsdttGk8x3nNY9ybc7LDa"
  ],
  "compression": "none",
  "packed_context_free_data": "",
  "packed_trx": "5bc23c5b4f200bf0f59c0000000001000000006405af91000000000000bc3e010000000000a092e100000000a8ed3232100000000000a092e1010000000000000000"
}
---------------------
RESPONSE:
---------------------
{
  "code": 500,
  "message": "Internal Service Error",
  "error": {
    "code": 3090003,
    "name": "unsatisfied_authorization",
    "what": "provided keys, permissions, and delays do not satisfy declared authorizations",
    "details": [{
        "message": "transaction declares authority '{\"actor\":\"anorak\",\"permission\":\"active\"}', but does not have signatures for it under a provided delay of 0 ms, provided permissions [{\"actor\":\"market\",\"permission\":\"eosio.code\"}], and provided keys []",
        "file": "authorization_manager.cpp",
        "line_number": 409,
        "method": "check_authorization"
      },{
        "message": "",
        "file": "apply_context.cpp",
        "line_number": 62,
        "method": "exec_one"
      }
    ]
  }
}
---------------------
Error 3090003: provided keys, permissions, and delays do not satisfy declared authorizations
Ensure that you have the related private keys inside your wallet and your wallet is unlocked.
Error Details:
transaction declares authority '{"actor":"anorak","permission":"active"}', but does not have signatures for it under a provided delay of 0 ms, provided permissions [{"actor":"market","permission":"eosio.code"}], and provided keys []

Error:

"message": "transaction declares authority '{\"actor\":\"anorak\",\"permission\":\"active\"}', but does not have signatures for it under a provided delay of 0 ms, provided permissions [{\"actor\":\"market\",\"permission\":\"eosio.code\"}], and provided keys []",
        "file": "authorization_manager.cpp",
        "line_number": 409,
        "method": "check_authorization"

File location:

https://github.com/EOSIO/eos/blob/5875549c955db2d0da05347d9aeb4c2fb5ecb898/libraries/chain/authorization_manager.cpp#L409

  • I deleted my answer because it seemed to help others. – smarteasy Jul 3 '18 at 16:15
1

I think there might be a problem with the original article. I have not actually run this code, but I will think about it in common sense.

In the buy function, to transfer, it seems that the authority should be set as follows.

action(permission_level {_self,N(active)}, N(anorak), N(transfer), make_tuple(buyer, _self, productPrice, string(""))).send();

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.