Thanks in advance for any help.

I can't seem to get on_notify to work (attempting to trigger for any tokens sent to the contract, but for the example I've tested both * and eosio.token)

The method:

[[eosio::on_notify("eosio.token::transfer")]]void mycontract::transfer( name from, name to, asset quantity, string memo){


Addstats/table declaration:

void competeos::addstatest(int amount){
        stats_def statstable(_self, _self.value);
        stat newstats;
          statstable.set(newstats, _self);
          newstats = statstable.get();
        newstats.counter += amount;
        statstable.set((newstats), _self);

    typedef eosio::singleton<"stats"_n, stat> stats_def;
    //tested with and without this stats line, here for another issue...
    typedef eosio::multi_index<"stats"_n, stat> dump_for_stats_def;

I'm sure that the addstattest method works because an exact copy of it is also set up as addstat as an action, and it works reliably.

As a side note, although the stats table counter does increase over time, whenever i query the table/singleton using cleos/a ram explorer, it always displays 1111115 - although other methods in my code show such as the addstat action show that it is increasing when I access it in ways that it sets the value, it just isn't directly query-able for some reason. If anyone has any insight here as well, it would be appreciated.

Anyways back to the initial question - I can't get the on_notify transfer method to trigger when tokens (eosio.token EOS tokens on the kylin network from another test account, in this case) are sent to it. This addstattest method seems like the easiest trace-able way to seeing whether it's triggering or not, as there's no requireauth in there or anything, but the only other requirement I've seen are to set permissions, which I've done using two methods:

cleos -u $BP_URL set account permission myaccountname myaccountname --add-code -p myaccountname@owner

as well as

cleos -u $BP_URL set account permission myaccountname active '{"threshold" : 1, "keys" : [{"key": "ActiveAccountPublicKey", "weight": 1}], "accounts" : [{"permission":{"actor": "myaccountname" ,"permission":"eosio.code"},"weight":1}], "waits":[]}}' owner -p nyaccountname@owner

Finally, I've also separated my code into an hpp file and cpp file so that the declaration for the on_notify is instantiated in the header (this was recommended to me by someone in the telegram channel).

Otherwise, there's little documentation on the use of this functionality, but it also seems like it should be pretty straight-forward. Any help would be greatly appreciated.


3 Answers 3

  1. Are you sure the problem is that the notification handler doesn't trigger, I would suggest trying to check(false, "notification handler triggered successfully"); at the beggining mycontract::transfer to be 100% sure.

  2. It would be a lot easier to help you out if you could attach all the relevant code. (both the .hpp and the .cpp)

  • I appreciate the help, you didn't give the answer but did make a good point about using an assertion check to see if it triggered or not. I was hesitant to upload my full codebase because very little of it was relevant to this issue and seemed like it would just complicate things. Ultimately the answer was not able to be extrapolated from my question, so I'm upvoting but marking my answer below as correct. Thank you for taking the time! Commented Jan 6, 2020 at 1:26

The resolution turns out to be removing the end EOSLIB_SERIALIZE macro for the contract. Unfortunately this causes a conflict with the DAPP services, as at least the oracle (still need to test others) require CONTRACT_END() which just passes through to EOSLIB_SERIALIZE(), but the on_notify needs to call a DSP service when triggered, so I'm now trying to figure out how to include both features (on_notify and DSP services) and have the contract run for both of them.

Otherwise, if anyone else comes across this, the major aspects needed are:

Set permissions for eosio.code for the contract, using the owner account permission, but setting it for the public key - at least that's the account I'm deploying the contract on, my active account, so that's what worked for me. ($ means replace with your own):

cleos -u "$Network_Endpoint_URL" set account permission $contractname active '{"threshold" : 1, "keys" : [{"key": "$publickey", "weight": 1}], "accounts" : [{"permission":{"actor": "$contractname" ,"permission":"eosio.code"},"weight":1}], "waits":[]}}' owner -p $contractname@owner

Then be sure to remove the EOSLIB_SERIALIZE macro from the end of the contract code, I haven't found a way to get on_notify to trigger while it's included.

With these conditions met, the contract executes using the code from my question.


If you are using EOSIO_DISPATCH with ACTION keyword, then replace ACTION keyword with [[eosio::action]] void from your .hpp file and remove EOSIO_DISPATCH from your .cpp file of smart contract.

As EOSIO_DISPATCH blocks eosio::on_notify.

Please closely check eosio.token contract you will get how use. https://github.com/EOSIO/eosio.contracts/tree/master/contracts/eosio.token

Original Answer on Why is [[eosio::on_notify(“eosio.token::transfer”)]] not working?

Your Answer

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

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