1

I have written a smart contract and I want to start testing it, it contains an apply function, which currently checks for a transfer, and then calls the appropriate function:

 void mycontract::apply(account_name contract, account_name act)
 {
    switch(act)
    {
      case N(transfer):
        eosio_assert(contract == N(eosio.token), "MyContract | use eosio.token");
        on(unpack_action_data<eosio::currency::transfer>());
        break;
    }
  }

I also have the C version, which does not belong to the mycontract class:

  extern "C" 
  {
    [[noreturn]] void apply( uint64_t receiver, uint64_t code, uint64_t action )
    {
      mycontract _mycontract(receiver);

      if(code == N(eosio.token))
      {
        switch(action) {

          case N(transfer):
            _mycontract.on(eosio::unpack_action_data<eosio::currency::transfer>());
            break;

          default:
            break;
        }
      }
      eosio_exit(0);
    }
  }  

Finally, I try to add the contract to my local nodeos:

cleos set contract contractowner ../mycontract/ -p contractowner

I then receive the following error message, which I don't understand:

Error 3070002: Runtime Error Processing WASM
Error Details:
Smart contract's apply function not exported; non-existent; or wrong type
pending console output: 

Does anyone know what could be causing this error message, or how I could go about debugging it further?

EDIT: It also doesn't work if I use the macro:

EOSIO_ABI( eosio::mycontract, (on) )
  • what about EOSIO_ABI(mycontract, (on))? – confused00 Jul 22 '18 at 23:52
1

UPDATE:

Based on the details you provided in the comments, I think the error might be coming from how you are compiling the code. You said you are running these commands:

eosiocpp -o mycontract.wasm *.cpp
eosiocpp -o mycontract.wast *.cpp
eosiocpp -g mycontract.abi mycontract.cpp

when you should actually be running these:

eosiocpp -o mycontract.wast mycontract.cpp

which will generate both the .wast and .wasm with just one command, and

eosiocpp -g mycontract.abi mycontract.hpp

which should receive the .hpp file which needs to be properly annotated with //@action and //@abi table <table_name> <index_type> directives for the command to generate the .abi successfully.

You can check this simple contract files for a good example of the annotations and macros that are required for the compilation to work. Also note that you should give the specific file to the eosiocpp command, not just "all .cpp files" like you were doing with *.cpp.

Previous answer:

I would recommend not trying to write the apply function manually and instead use the EOSIO_ABI macro as shown in this contract:

EOSIO_ABI( eosio::token, (destroytoken)(destroyacc) )

This way you simply write a class that represents the contract and inherits from eosio::contract, and then define some actions inside of it as methods (keeping their names 12 chars or shorter) and then use the macro at the end like this:

EOSIO_ABI( <YOUR CONTRACT CLASS>, (<ACTION1>)(<ACTION2>)(<ETC>) )

This will create the apply function for you and everything will work nicely!

More info here: https://developers.eos.io/eosio-cpp/docs/file-structure#section-the-eosio_abi-macro

  • Thanks for the answer, unfortunately this also didn't work, giving the same error message. I wrote exactly this: EOSIO_ABI( eosio::mycontract, (on) ), outside of the eosio namespace. – Phillip Hamnett - EOS42 Jul 22 '18 at 20:44
  • 1
    Did it compile properly without errors when you run eosiocpp? Is your contract class defined inside the eosio namespace? I would recommend starting from a sample contract (like the one I linked) and modifying the code from there. Otherwise please share the whole code so we can see exactly what might be going wrong. – Andres Berrios Jul 22 '18 at 22:41
  • Yes the contract class is defined in the eosio namespace, and yes it compiles without errors when I run eosiocpp. The commands I use to compile are: eosiocpp -o mycontract.wasm *.cpp, eosiocpp -o mycontract.wast *.cpp, eosiocpp -g mycontract.abi mycontract.cpp – Phillip Hamnett - EOS42 Jul 23 '18 at 5:03
  • 1
    @PhillipHamnett I updated the answer in response to your comment – Andres Berrios Jul 23 '18 at 18:27
  • 1
    Philip, you are right, I had a typo in the wasm extension, it was supposed to be wast, I updated the answer now, thanks! About your followup question: You don't need to write everything in a single file, you can include other files using #include "other.cpp" and define other classes there, but when you compile using eosiocpp you should point it only to the main cpp file, unless you use #include "other.hpp", since then you would also need to point it to the cpp files for the implementation, and the *.cpp would work well I think. – Andres Berrios Jul 24 '18 at 14:22

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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