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?

3 Answers 3

1

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

2
  • 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) ) Jul 14, 2018 at 21:31
  • 1
    you don't need to define, because the parent is already do that
    – Jimmy Guo
    Jul 15, 2018 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))
1
  • But how can i access the table they are not generated in my .abi file?? Jan 18, 2019 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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