My contract action causes error message
assertion failure with message: read
My action code is here
void GeneMelee::buy(account_name buyer,uint64_t sale_key,asset price)
{
//check existence
saletable sales(_self,_self);
auto which = sales.find(sale_key);
eosio_assert(sales.end() != which,"no such item on sale");
//check whether the transferred quantity is over the price
eosio_assert(price.symbol == which->price.symbol,"the payment is not the seller's required currency!");
eosio_assert(price.amount >= which->price.amount,"the payment is not enough to buy the item!");
action(
permission_level{_self,N(active)},
N(eosio.token),N(transfer),
std::make_tuple(_self,which->player,price,"payment from buyer")
).send();
//hand over item
switch(which->type) {
case static_cast<int>(ForSale::ELF):
{
elftable seller_elfs(_self,which->player);
auto which_elf = seller_elfs.find(which->item_key);
eosio_assert(seller_elfs.end() != which_elf,"seller don't have the elf for sale");
elftable buyer_elfs(_self,buyer);
buyer_elfs.emplace(_self,[&](auto & elf){
elf.elf_key = buyer_elfs.available_primary_key();
elf.genre = which_elf->genre;
elf.level = which_elf->level;
elf.appearance = which_elf->appearance;
elf.dna = which_elf->dna;
elf.capabilities = which_elf->capabilities;
elf.last_feed_datetime = which_elf->last_feed_datetime;
elf.feed_interval = which_elf->feed_interval;
elf.bgr = which_elf->bgr;
});
seller_elfs.erase(which_elf);
}
break;
case static_cast<int>(ForSale::GENE):
{
genetable seller_genes(_self,which->player);
auto which_gene = seller_genes.find(which->item_key);
eosio_assert(seller_genes.end() != which_gene,"seller don't have the gene for sale");
genetable buyer_genes(_self,buyer);
buyer_genes.emplace(_self,[&](auto & gene) {
gene.gene_key = buyer_genes.available_primary_key();
gene.segment_id = which_gene->segment_id;
gene.delta_appearance = which_gene->delta_appearance;
gene.delta_capabilities = which_gene->delta_capabilities;
gene.delta_bgr = which_gene->delta_bgr;
});
seller_genes.erase(which_gene);
}
break;
default:
eosio_assert(0,"unknown type of item!");
}
//remove from saling table
sales.erase(which);
}
which part of the code could cause the error message? One thing I can't understand is that I added eosio_assert(0,"here"); to the last line of the action. when I call the action, my assertion can always be triggered. it seems the error occurs after the action is called.
Inline actions are always called after the main action no matter where you put it in your source code.
the problem is caused by not giving memo in string object.
So
action(
permission_level{_self,N(active)},
N(eosio.token),N(transfer),
std::make_tuple(_self,which->player,price,"payment from buyer")
).send();
failed and
action(
permission_level{_self,N(active)},
N(eosio.token),N(transfer),
std::make_tuple(_self,which->player,price,std::string("payment from buyer"))
).send();
succeed?
I think it's a bug. And there's someone else met the same issue. see here
@heifner
@spartucus that looks like a bug to me too. Please create an issue with your example in the wasmsdk repo; that鈥檚 where it needs to be fixed.
@spartucus This is not a bug per se, it is a limitation of make_tuple. The types const char* and std::string are not the same, so make_tuple will treat the const char* as a pointer and will send over that (which is garbage), and the type of the memo field is expecting an std::string, so explicit construction of std::string is needed to make std::make_tuple do the right thing.
Most helpful comment
@spartucus This is not a bug per se, it is a limitation of make_tuple. The types const char* and std::string are not the same, so make_tuple will treat the const char* as a pointer and will send over that (which is garbage), and the type of the memo field is expecting an std::string, so explicit construction of std::string is needed to make std::make_tuple do the right thing.