2

Can we have a function in a smart contract to be executed automatically after some time?

for example, transfer some tokens after every 5 seconds.

2
  • 2
    Call the action as a deferred transaction recursively. Commented Nov 6, 2018 at 6:44
  • explain in detail sir please I don't know anything about the deferred transaction? Commented Nov 6, 2018 at 6:53

3 Answers 3

2

First of all you need to push a transaction initially and you have to write a deferred transaction that call itself recursively after a certain period of time. You should also write some basecase . Basecase condition can be stored inside a table (need to check every time). Deferred transaction can be seen as @John Haager metion. You can write a @abi action that call this transfer action inside you recursion like this:

// @abi action
void  Democontract::actionDemo(account_name from, string memo, uint64_t duration, uint64_t interval)
{
    uint64_t max_delay = 50;
    string appending_char = "1";

    print(int(duration));
    eosio_assert((((memo.length() == 11) || (memo.length() == 12))), "\n check the length of memo");

    //_ttab ttabs(_self, _self);
    // you use table values here from your table (if you are using table in your code )

    eosio::transaction txn{};

    if (duration < interval)
    {
        print("reached final limit all transaction executed---");
    }
    else if (duration >= interval)
    {

        uint64_t delay = 0;

       //call your transfer action here

        if (duration >= interval)
        {
            //delay interval , duration - interval
            print("duration > interval_________\n");
            txn.actions.emplace_back(
                eosio::permission_level(from, N(active)),
                N(contractname),
                N(actionDemo),
                std::make_tuple(from, memo, duration - interval, interval));
            txn.delay_sec = max_delay;
            txn.send(eosio::string_to_name(memo.c_str()), from);
        }
        else if (duration < interval)
        {
            //delay duration, 0
            print("duration <====== interval_________\n");
            txn.actions.emplace_back(
                eosio::permission_level(from, N(active)),
                N(contractname),
                N(actionDemo),
                std::make_tuple(from, memo, uint64_t(0), interval));
            txn.delay_sec = duration;
            txn.send(eosio::string_to_name(memo.c_str()), from);
        }
    }

You can also modify this code to execute transaction more more that 45 days interval time.I also don't write transfer action you can call it inline as i mention in comment.duration(suppose you want this for 2 days) and Max_day is the interval you want to execute your action (after a specific time interval) rest of the things you can understand easily.

1

The deferred transaction method will work for a while, however Block One have said that there is no guarantee that a deferred transaction will execute at all. It could simply fail and in that case your code will probably end up in a bad state if it relies on this 5 second interval transfer.

An alternative method would be to set up a cron job to call the action from a server, although this has the disadvantage of semi-centralising the system.

You can combine both worlds:

  1. Create a table that keeps track of the last time the transfer occured.
  2. Have your transfer call itself recursively as a deferred transaction.
  3. Also call your cron job to make sure that the transaction succeeds.
  4. Make sure to include something in the code that says something like eosio::assert(now() -last_transfer > 5*ONE_SECOND,"Can't call this now, must wait at least 5 seconds");
0

A deferred transaction can be created and submit that will be executed at the specified future time. If you want the action to execute again, then the action can simply schedule a new deferred transaction to invoke itself.

// Create a deferred transaction
transaction out{};
out.actions.emplace_back(
        permission_level{_self, "active"_n},
        _self,
        "myaction"_n,
        std::make_tuple(actionParam)
);
out.delay_sec = refundInterval;
out.send(deferredTxID, _self);

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.