How can a contract run itself at a later time?

  • In my blockchain application, I would like to have an event triggered at a later time, hours or perhaps even days after the application has most recently received a transaction from a user. How can I create an "event" that will trigger after a certain amount of time has passed?

  • Lazy vs Eager Execution

    There are two fundamental ways of designing a contract to be called at a later time: lazy evaluation or eager evaluation.

    Lazy evaluation means that the contract's state will be updated only when needed. This often makes sense for contracts that naturally incentivise users to call them at a future date.

    An example of this might be a trust fund contract that will remain locked until someone's 18th birthday. This individual would be motivated to execute the dispersal of those funds at that time.

    A more complex example is an interest-bearing contract. Say I deposit 1 ETH, and every month I get 1% interest, compounding.

    There are two ways to go about this:

    1. The lazy way: When I want to withdraw my money, I call the contract and it calculates my balance, based on the interest rate, my last known balance, and the elapsed time.
    2. The eager way: I use the Ethereum Alarm Clock or some similar service to call the claimInterest() function of the contract, which calculates that month's interest and debits my balance.

    In this case, lazy evaluation makes sense, because it is easy to calculate the current state based on the past state and elapsed time.

    Eager evaluation is useful when state transitions are

    1. Computationally expensive
      • Working with large storage sets, sorting large lists, etc.
    2. Nondeterministic
    3. Lacking incentives
      • Data reconciliation, various non-monetary contracts.
    4. Reliant on another contract
      • If the contract needs to accept input from or send transactions to another contract

    Call Scheduling with Ethereum Alarm Clock

    The Ethereum Alarm Clock service supports scheduling a contract to be called at a specified block in the future. The underlying mechanism is essentially an abstraction of incentive based solution above that allows arbitrary private key based accounts to have an incentive to execute calls on arbitrary contracts.

    The protocol has been audited and deployed on mainnet. It's fully functioning right now.

    Call scheduling can be done with the following code:

    const { EAC, Util } = require('@ethereum-alarm-clock/lib');
    const moment = require('moment');
    
    const web3 = Util.getWeb3FromProviderUrl('ws://localhost:8545');
    
    const eac = new EAC(web3);
    
    async function scheduleTransaction() {
        const receipt = await eac.schedule({
            toAddress: '0xe87529A6123a74320e13A6Dabf3606630683C029',
            windowStart: moment().add('1', 'day').unix() // 1 day from now
        });
    
        console.log(receipt);
    }
    
    scheduleTransaction();
    

    The example above uses @ethereum-alarm-clock/lib. which is minimal library to use Ethereum Alarm Clock protocol.

    More explanatory instructions can be found here. There's also video tutorial.

    Part of scheduling the call is providing sufficient ether to pay for the future gas costs for executing the call, as well as for the payments that go to the executor of the call and fee to protocol creators (if specified).

    When this call is scheduled, a new contract is deployed that manages all of the details for call execution.

    Execution

    The Alarm service requires a private key based Ethereum account to execute the call at the specified time. This behavior is motivated by a payment value that is associated with each scheduled call. When the target block occurs, the executor of the call is fully reimbursed for their gas costs as well as paid from the specified payment amount for their service.

    This process of monitoring the Alarm service for upcoming calls and executing them can be accomplished using TimeNode. Anyone can be a TimeNode, here's comprehensive tutorial and video how to become one: How to Run a TimeNode.

    Configurable options for scheduled calls

    • toAddress - Recipient address
    • callData - Transaction data
    • callGas - Gas limit for transaction execution in the future
    • callValue - Future transaction value in Wei
    • windowSize - Size of the time window for execution, in blocks or seconds
    • windowStart - Block number / UNIX timestamp of when the window for execution should open
    • gasPrice - Future gas price for execution
    • fee - Fee (in Wei) paid to Ethereum Alarm Clock maintainers for using scheduling
    • bounty - Payment for transaction executor
    • requiredDeposit - Executor deposit, when it tries to execute scheduled transaction

    Costs

    The Alarm service attempts to create open market for call scheduling. The scheduler may specify any amount for both the Bounty and Fee values and those executing calls are free to choose which calls they are willing to execute.

    At the time of scheduling, sufficient ether must be provided to pay for both the gas costs as well as the associated payments and fees. After execution, any remaining ether is automatically returned to the scheduler of the call.

    Testing

    The Alarm service is available for testing on the test networks such as Kovan and Ropsten. There are TimeNodes running which execute transactions on these networks.

    Guarantees

    The Alarm service is a marketplace for call scheduling and cannot provide any guarantees that a scheduled call will be executed. For the service to operate, it requires people to initiate the transactions that execute scheduled calls.

    Protection

    As the scheduler of a function call, you can count on the following:

    • Your contract will be called with the exact call data it was configured with.
    • Your contract will not be called before or after the window of blocks between the target block and the number of blocks after specified by the grace period.

    Trustlessness

    The Alarm service does not grant any special permissions to any party and is 100% open source.

    Documentation and other links

    See my comment on the other answer. First to combine the two gets the check mark!

    I added a section at the top which addresses (briefly) the concept of a contract incentivizing certain actions.

    That's close, but it doesn't quite get to the heart of linagee's answer which is that you can often restructure a contract so that the "real" balances are just updated to the latest numbers the first time someone calls on them. I'd also like to see some description of how developers should decide between the "lazy evaluation" approach and the ethereum alarm clock approach, like I mentioned in my comment.

    You clearly have something specific in mind. I've released the answer to be considered a community wiki answer. Feel free to edit the answer to include the concept you're thinking about.

    I added a quick blurb about lazy evaluation and the different options. I think it needs stronger examples, though.

    We can always improve it later, but you've got the bulk of what I was looking for there, so I've marked it accepted.

    You claim "Your contract will not be called before or after the window of blocks between the target block and the number of blocks after specified by the grace period." What's stopping someone from calling the contract at any time?

    No news since then. Unfortunately it looks like this project is dead.

    I think your answer should start by mentioning that there is no native way to do this A smart contact cannot call itself in the future without assistance of a service like yours. Question about your code sample – Since the future execution time is set in blocks rather than in time values does that mean that the actual future execution time is highly variable as it depends on the specific block times of all blocks up until the target?

    Project is alive and well. It has been integrated to mycrypto.com. You can read more on https://www.ethereum-alarm-clock.com.

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM