Quickstart

Introduction

This guide is inteded for smart contract developers that may want to use the EAC services from within their own applications. Since all the functionality of the Alarm Clock is built into the Ethereum chain via smart contracts, it can be accessed from other contracts. This makes it useful as a foundational tool to design and implement more complex utilities that depend on future transactions. For this guide we will be using the Solidity language. If you are unfamiliar with Solidity we recommend you familiarize yourself with its documentation first.

Scheduling your first transaction

The first step is to establish how we will interact with the EAC service’s Scheduler contract. We can use the Scheduler Interface to accomplish this. The Scheduler interface contract contains some logic that is shared between both the Block Scheduler and the Timestamp Scheduler. The function that we are interested in is the schedule() function. See the signature of this function below:

function schedule(address   _toAddress,
                  bytes     _callData,
                  uint[7]   _uintArgs)
    doReset
    public payable returns (address);

SchedulerInterface.sol is an abstract contract that exposes the API for the Schedulers including the schedule() function that we will use in the contract we write.

function schedule which will return the address of the newly created TransactionRequest contract. We will import this contract into the contract we write so to ensure that our contract will be compliant with the official API of the EAC.

Now lets write a simple contract that can use the scheduling service.

pragma solidity 0.4.19;

import 'contracts/Interface/SchedulerInterface.sol';

/// Example of using the Scheduler from a smart contract to delay a payment.
contract DelayedPayment {

    SchedulerInterface public scheduler;

    uint lockedUntil;
    address recipient;

    function DelayedPayment(
        address _scheduler,
        uint    _numBlocks,
        address _recipient
    ) {
        scheduler = SchedulerInterface(_scheduler);
        lockedUntil = block.number + _numBlocks;
        recipient = _recipient;

        scheduler.schedule.value(2 ether)(
            recipient,              // toAddress
            "",                     // callData
            [
                2000000,            // The amount of gas to be sent with the transaction.
                0,                  // The amount of wei to be sent.
                255,                // The size of the execution window.
                lockedUntil,        // The start of the execution window.
                30000000000 wei,    // The gasprice for the transaction (aka 30 gwei)
                12345 wei,          // The fee included in the transaction.
                224455 wei,         // The bounty that awards the executor of the transaction.
                20000 wei           // The required amount of wei the claimer must send as deposit.
            ]
        );
    }

    function () {
        if (this.balance > 0) {
            payout();
        } else {
            revert();
        }
    }

    function payout()
        public returns (bool)
    {
        require(getNow() >= lockedUntil);
        recipient.transfer(this.balance);
        return true;
    }

    function getNow()
        internal view returns (uint)
    {
        return block.number;
    }

}

The contract above is designed to lock away whatever ether it is given for numBlocks blocks. In its constructor, it makes a call to the schedule method on the scheduler contract. We would pass in the address of the scheduler we would want to interact with as the first parameter of the constructor. For instance, if we wanted to use the Block Scheduler that is deployed on the Ropsten test net we would use address 0x96363aea9265913afb8a833ba6185a62f089bcef.

The function only takes 3 parameters at deployment, with the 7 parameters being into the schedule function being set by the developer of the smart contract. The schedule function takes 7 arguments, each of which we will go over in order.

  • address toAddress: The address which the transaction will be sent to.
  • bytes callData: The bytes that will be used as the data for the transaction.
  • uint callGas: The amount of gas that will be sent with the transaction.
  • uint callValue: The amount of ether (in wei) that will be sent with the transaction.
  • uint8 windowSize: The number of blocks after windowSize during which the transaction will still be executable.
  • uint windowStart: The first block number that the transaction will be executable.
  • uint gasPrice: The gas price which must be sent by the executing party to execute the transaction.
  • uint fee: The fee amount included in the transaction.
  • uint payment: The payment included in the transaction.

Let’s look at the other function on this contract. For those unfamiliar with solidity, the function without a name is known as the fallback function. The fallback function is what triggers if no method is found on the contract that matches the sent data, or if data is not included. Usually, sending a simple value transfer function will trigger the fallback function. In this case, we explicitly pass an empty string as the callData variable so that the scheduled transaction will trigger this function when it is executed.

When the fallback function is executed, if the contract has a balance (which it does since we sent it 2 ether on deployment) it will route the call into the payout() function. The payout() function will check the current block number and check if it is not below the lockedUntil time or else it reverts the transaction. After it checks that the current block number is greater than or equal to the lockedUntil variable, the function will transfer the entrie balance of the contract to the specified recipient.

As can be seen, this will make it so that a payment is scheduled for a future date but won’t actually be sent until that date. This example uses a simple payment, but the EAC will work with arbritrary logic. As the logic for a scheduled transaction increases, be sure to increase the required callGas in accordance. Right now, the gas limit for a transaction is somewhere in the ballpark of 8,000,000 so there’s plenty of wiggle room for experimentation.