Call Execution ============== Call execution is the process through which scheduled calls are executed at their desired block number. After a call has been scheduled, it can be executed by account which chooses to initiate the transaction. In exchange for executing the scheduled call, they are paid a small fee of approximately 1% of the gas cost used for executing the transaction. Executing a call ---------------- Use the ``execute`` function to execute a scheduled call. This function is present on the call contract itself (as opposed to the scheduling service). * **Solidity Function Signature:** ``execute() public`` * **ABI Signature:** ``0x61461954`` When this function is called, the following things happen. 1. A few checks are done to be sure that all of the necessary pre-conditions pass. If any fail, the function exits early without executing the scheduled call: * the call has not already been called. * the current block number is within the range this call is allowed to be executed. * the caller is allowed to execute the function (see caller pool) 2. The call is executed 3. The gas cost and fees are computed and paid. 4. The call contract sends any remaining funds to the scheduling address. Payment ^^^^^^^ Each scheduled call sets its own payment value. This can be looked up with the ``basePayment`` accessor function. The final payment value for executing the scheduled call is the ``basePayment`` multiplied by a scalar value based on the difference between the gas price of the executing transaction and the gas price that was used to schedule the transaction. The formula for this scalar is such that the lower the gas price of the executing transaction, the higher the payment. Setting transaction gas and gas price ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Each call contract has a ``suggestedGas`` property that can be used as a suggestion for how much gas the function call needs. In the case where this is set to zero it means the scheduler has not provided a suggestion. This suggested gas value should be used in conjuction with the ``basePayment`` and ``baseFee`` amounts with respect to the ether balance of the call contract. The provided gas for the transaction should not exceed ``(balance - 2 * (basePayment + baseFee)) / gasPrice`` if you want to guarantee that you will be fully reimbursed for gas expenditures. Getting your payment ^^^^^^^^^^^^^^^^^^^^ Payment for executing a call is sent to you as part of the executing transaction, as well as being logged by the ``CallExecuted`` event. Determining what scheduled calls are next ----------------------------------------- You can query the Alarm service for the call key of the next scheduled call on or after a specified block number using the ``getNextCall`` function * **Solidity Function Signature:** ``getNextCall(uint blockNumber) returns (address)`` * **ABI Signature:** ``0x9f927be7`` Since there may be multiple calls on the same block, it is best to also check if the call has any *siblings* using the ``getNextCallSibling`` function. This function takes a call contract address and returns the address that is scheduled to come next. When checking for additional calls in this manner, you should check the target block of each subsequent call to be sure it is within a range that you care about. * **Solidity Function Signature:** ``getNextCallSibling(address callAddress) returns (address)`` * **ABI Signature:** ``0x48107843`` .. note:: 40 blocks into the future is a good range to monitor since new calls must always be scheduled at least 40 blocks in the future. You should also monitor these functions up to 10 blocks before their target block to be sure they are not cancelled. The Freeze Window ----------------- The 10 blocks prior to a call's target block are called the **freeze window**. During this window, nothing about a call can change. This means that it cannot be cancelled or claimed. Claiming a call --------------- Claiming a call is the process through which you as a call executor can guarantee the exclusive right to execute the call during the first 16 blocks of the call window for the scheduled call. As part of the claim, you will need to put down a deposit, which is returned to you if you when you execute the call. Failing to execute the call will forfeit your deposit. Claim Amount ^^^^^^^^^^^^ A call can be claimed during the 255 blocks prior to the freeze window. This period is referred to as the claim window. The amount that you are agreeing to be paid for the call is based on whichever block the call is claimed on. The amount can be calculated using the following formula. * Let ``i`` be the index of the block within the 255 block claim window. * Let ``basePayment`` be the payment amount specified by the call contract. * If within the first 240 blocks of the window: ``payment = basePayment * i / 240`` * If within the last 15 blocks of the window: ``payment = basePayment`` This formula results in a linear growth from 0 to the full ``basePayment`` amount over the course of the first 240 blocks in the claim window. The last 15 blocks are all set at the full ``basePayment`` amount. A claim must be accompainied by a deposit that is at least twice the call's ``basePayment`` amount. Getting your Deposit Back ^^^^^^^^^^^^^^^^^^^^^^^^^ If you claim a call and do not execute it within the first 16 blocks of the call window, then you will risk losing your deposit. Once the first 16 blocks have passed, the call can be executed by anyone. At this point, the first person to execute the call will receive the deposit as part of their payment (and incentive to pick up claimed calls that have not been called). Claim API ^^^^^^^^^ To claim a contract * **Solidity Function Signature:** ``claim()`` * **ABI Signature:** ``0x4e71d92d`` To check what the ``claimAmount`` will be for a given block number use the ``getClaimAmountForBlock`` function. This will return an amount in wei that represents the base payment value for the call if claimed on that block. * **Solidity Function Signature:** ``getClaimAmountForBlock(uint blockNumber)`` * **ABI Signature:** ``0xf5562753`` This function also has a shortcut that uses the current block number * **Solidity Function Signature:** ``getClaimAmountForBlock()`` * **ABI Signature:** ``0x4f059a43`` You can check if a call has already been claimed with the ``claimer`` function. This function will return either the empty address ``0x0`` if the call has not been claimed, or the address of the claimer if it has. * **Solidity Function Signature:** ``claimer() returns (address)`` * **ABI Signature:** ``0xd379be23`` Safeguards ---------- There are a limited set of safeguards that Alarm protects those executing calls from. * Ensures that the call cannot cause the executing transaction to fail due to running out of gas (like an infinite loop). * Ensures that the funds to be used for payment are locked during the call execution. Tips for executing scheduled calls ---------------------------------- The following tips may be useful if you wish to execute calls. Only look in the next 265 blocks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Since calls cannot be scheduled less than 265 blocks in the future, you can count on the call ordering remaining static for the next 265 blocks. No cancellation in next 265 blocks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Since calls cannot be cancelled less than 265 blocks in the future, you don't need to check cancellation status during the 265 blocks prior to its target block. Check that it was not already called ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If you are executing a call after the target block but before the grace period has run out, it is good to check that it has not already been called. Compute how much gas to provide ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If you want to guarantee that you will be 100% reimbursed for your gas expenditures, then you need to compute how much gas the contract can pay for. The *overhead* involved in execution is approximately 140,000 gas. The following formula should be a close approximation to how much gas a contract can afford. * let ``gasPrice`` be the gas price for the executing transaction. * let ``balance`` be the ether balance of the contract. * let ``claimerDeposit`` be the claimer's deposit amount. * let ``basePayment`` be the base payment amount for the contract. This may either be the value specified by the scheduler, or the ``claimAmount`` if the contract has been claimed. * ``gas = (balance - 2 * basePayment - claimerDeposit) / gasPrice``