5

I am trying to inherit the 'eosio.token' contract found in '/eos/contracts/eosio.token/' into my new class 'my.token'

My CMakeLists.txt looks like

file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)

add_wast_executable(TARGET my.token
  INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
  LIBRARIES libc++ libc eosiolib eosio.token
  DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)

my.token.hpp is

#include <eosio.token/eosio.token.hpp>

namespace eosio {

class mytoken : public token {

public:

    mytoken( account_name self ) : token( self ) {}

};

}

And my.token.cpp is just

#include "my.token.hpp"

EOSIO_ABI(eosio::mytoken, (create)(issue)(transfer) )

When I compile with

$cd ~/eos/build
$make

It builds fine. No problem. But when I go to deploy the contract with cleos set contract mytoken ~/eos/build/contracts/my.token/

I get the following error in the nodeos console output:

2068185ms thread-0   http_plugin.cpp:405           handle_exception     ] FC Exception encountered while processing chain.push_transaction
2068185ms thread-0   http_plugin.cpp:406           handle_exception     ] Exception Details: 10 assert_exception: Assert Exception
!"unresolvable": env._ZN5eosio5token6createEyNS_5assetE
    {"module":"env","export":"_ZN5eosio5token6createEyNS_5assetE"}
    thread-0  wasm_interface.hpp:41 resolve

    {"mod_name":"env","export_name":"_ZN5eosio5token6createEyNS_5assetE"}
    thread-0  wasm_interface.hpp:43 resolve

    {"_pending_console_output.str()":""}
    thread-0  apply_context.cpp:62 exec_one

Does anyone know how to do this, or is it not supported yet?

1

Because now the EOS only support to build one cpp file, so you can include the eosio.token.cpp in your cpp file.

| improve this answer | |
  • Hey, thanks a lot for the help. Now I am getting the error error: redefinition of 'apply' EOSIO_ABI(eosio::my.token, (create)(issue)(transfer) ) – Magic Man Xpress Jul 14 '18 at 21:31
  • 1
    you don't need to define, because the parent is already do that – Jimmy Guo Jul 15 '18 at 6:40
1

the only way it worked for me is when I first redefined EOSIO_ABI macro to dummy , then included eosio.token/eosio.token.cpp , then redefined it back to what it was so I could use it in mytoken.cpp

#undef EOSIO_ABI
#define EOSIO_ABI( TYPE, MEMBERS )

#include <eosio.token/eosio.token.cpp>

#undef EOSIO_ABI
#define EOSIO_ABI( TYPE, MEMBERS ) \
extern "C" { \
   void apply( uint64_t receiver, uint64_t code, uint64_t action ) { \
      auto self = receiver; \
      if( action == N(onerror)) { \
         /* onerror is only valid if it is for the "eosio" code account and authorized by "eosio"'s "active permission */ \
         eosio_assert(code == N(eosio), "onerror action's are only valid from the \"eosio\" system account"); \
      } \
      if( code == self || action == N(onerror) ) { \
         TYPE thiscontract( self ); \
         switch( action ) { \
            EOSIO_API( TYPE, MEMBERS ) \
         } \
         /* does not allow destructor of thiscontract to run: eosio_exit(0); */ \
      } \
   } \
} \

Also , if you are using same function names in your derived class as in eosio.token you will get this error from ABI generator

find_struct(method_name) == nullptr: action already exists issue

if the reason for subclassing is to add logic to your token say you want to add some additional logic to action issue() that will augment standard logic I would suggest rename it to issuexyz() and then do

EOSIO_ABI( mytoken::token, (create)(issuexyz)(transfer)

Your code would look like that

#include <eosiolib/dispatcher.hpp>

#undef EOSIO_ABI
#define EOSIO_ABI( TYPE, MEMBERS )

#include <eosio.token/eosio.token.cpp>

#undef EOSIO_ABI
#define EOSIO_ABI( TYPE, MEMBERS ) \
extern "C" { \
void apply( uint64_t receiver, uint64_t code, uint64_t action ) { \
      auto self = receiver; \
      if( action == N(onerror)) { \
         /* onerror is only valid if it is for the "eosio" code account and authorized by "eosio"'s "active permission */ \
         eosio_assert(code == N(eosio), "onerror action's are only valid from the \"eosio\" system account"); \
      } \
      if( code == self || action == N(onerror) ) { \
         TYPE thiscontract( self ); \
         switch( action ) { \
            EOSIO_API( TYPE, MEMBERS ) \
         } \
         /* does not allow destructor of thiscontract to run: eosio_exit(0); */ \
      } \
   } \
} \

namespace mytoken {

using namespace eosio;

class mytoken : public token {
   using base = token;

public:

    mytoken( account_name self ) : base( self ) {}
    void issuexyz(account_name to, const asset &quantity, const std::string &memo, bool myflag) {

        if(myflag) {
           //custom logic goes here say you want to add additional checks
        }
        base::issue(to, quantity, memo);
    } 

};

}

EOSIO_ABI( mytoken::mytoken, (create)(issuexyz)(transfer))
| improve this answer | |
  • But how can i access the table they are not generated in my .abi file?? – Nirdesh Kumar Choudhary Jan 18 '19 at 5:41
0

At the time of my answer, the issue #43 is still open. I guess they had/have other plans for the issue.

And I guess that is connected to ABI generation. I have tried to inherit my contract from eosio::token and don't see token's tables in *.abi file.

| 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.