Моя цель — запланировать звонок один раз в день.
[В] Можно ли использовать рекурсивную функцию для планирования звонка один раз в день с помощью планировщика Ethereum Alarm Clock?
Пример из следующего ответа https://ethereum.stackexchange.com/a/87/4575 :
contract SchedulerAPI { function scheduleCall(address contractAddress, bytes4 abiSignature, uint targetBlock) public returns (address); } contract CallMeLater { // The address of the v0.6.0 Alarm Clock scheduler contract. address constant Scheduler = SchedulerAPI(0xe109ecb193841af9da3110c80fdd365d1c23be2a); function CallMeLater() { // Schedule a call to the `callback` function Scheduler.value(2 ether).scheduleCall( address(this), // the address that should be called. bytes4(sha3("callback()")), // 4-byte abi signature of callback fn block.number + 5082, // the block number to execute the call ); //As we know 1 day duration (1440 minutes): 5082 blocks. } function callback() public { // whatever code you want executed. CallMeLater(); //added: recursive call. } }
Я добавил CallMeLater();
в конец callback()
функции, я полагаю, что будет новое расписание (на 1 день вперед), чтобы вызвать callback()
.
Решение
Протокол изменился с момента публикации вопроса. Можно выполнять рекурсивные вызовы, создав службу, которая, например, использует преимущества прокси-кошелька (для финансирования следующих вызовов).
Будильник Ethereum имеет пример RecurringPayment в своем репозитории. Это договор:
pragma solidity 0.4.24;
import "contracts/Interface/SchedulerInterface.sol";
/// Example of using the Scheduler from a smart contract to delay a payment.
contract RecurringPayment {
SchedulerInterface public scheduler;
uint paymentInterval;
uint paymentValue;
uint lockedUntil;
address recipient;
address public currentScheduledTransaction;
event PaymentScheduled(address indexed scheduledTransaction, address recipient, uint value);
event PaymentExecuted(address indexed scheduledTransaction, address recipient, uint value);
function RecurringPayment(
address _scheduler,
uint _paymentInterval,
uint _paymentValue,
address _recipient
) public payable {
scheduler = SchedulerInterface(_scheduler);
paymentInterval = _paymentInterval;
recipient = _recipient;
paymentValue = _paymentValue;
schedule();
}
function ()
public payable
{
if (msg.value > 0) { //this handles recieving remaining funds sent while scheduling (0.1 ether)
return;
}
process();
}
function process() public returns (bool) {
payout();
schedule();
}
function payout()
private returns (bool)
{
require(block.number >= lockedUntil);
require(address(this).balance >= paymentValue);
recipient.transfer(paymentValue);
emit PaymentExecuted(currentScheduledTransaction, recipient, paymentValue);
return true;
}
function schedule()
private returns (bool)
{
lockedUntil = block.number + paymentInterval;
currentScheduledTransaction = scheduler.schedule.value(0.1 ether)( // 0.1 ether is to pay for gas, bounty and fee
this, // send to self
"", // and trigger fallback function
[
1000000, // The amount of gas to be sent with the transaction. Accounts for payout + new contract deployment
0, // The amount of wei to be sent.
255, // The size of the execution window.
lockedUntil, // The start of the execution window.
20000000000 wei, // The gasprice for the transaction (aka 20 gwei)
20000000000 wei, // The fee included in the transaction.
20000000000 wei, // The bounty that awards the executor of the transaction.
30000000000 wei // The required amount of wei the claimer must send as deposit.
]
);
emit PaymentScheduled(currentScheduledTransaction, recipient, paymentValue);
}
}
В основном вы можете видеть, что функция конструктора payable
, это означает, что вы должны финансировать контракт при его создании. Это позволит финансировать будущие рекурсивные вызовы.
Хорошим примером для рассмотрения является повторяющийся будильник . Проект с открытым исходным кодом, и вы можете взглянуть на код.
Дезинформация в других ответах/комментариях
Что ж, другой ответ не учитывает, как работает будильник Ethereum — этот вызов запланирован, а не вызывается мгновенно. Это означает, что не будет бесконечного цикла, это больше похоже setInterval
на JavaScript.
Кто-то также дезинформирует в комментарии, что есть gracePeriod
, что означает: «Вы найдете параметр «gracePeriod», который говорит, что вы не можете сделать тот же вызов после 255 блоков». - но это тоже неправильно.
Сама связанная документация устарела, но в ней говорится:
uint8 gracePeriod: количество блоков после targetBlock, в течение которого этот вызов можно продолжать выполнять. Не может быть меньше 64 (по умолчанию: 255).
Таким образом, в этом примере gracePeriod может быть прочитан как ОКНО ВЫПОЛНЕНИЯ.
Проблема с предположением газа может быть там? Я предполагаю, что до тех пор, пока «эта функция способна принимать средства на газ», этот запланированный контракт будет действовать вечно.
Гейган
Гейган