Может ли контракт безопасно полагаться на block.timestamp?

Насколько безопасно использовать block.timestamp в качестве времени истечения контракта? Если майнер предоставляет неправильную временную метку в заголовке блока, сколько времени она может быть отключена, прежде чем она будет отклонена другими узлами? Есть ли стратегия сделать контракт более устойчивым к этому?

Ответы (3)

Не особенно , но это зависит от варианта использования.

Время блока зависит от следующих ограничений:

  • Если вы отметите свой блок слишком далеко в будущем, никто другой не будет строить на нем (майнеры не будут строить на блоке с отметкой времени «из будущего»).
  • Время вашего блока не может быть отмечено более ранним временем, чем время его родителя.
  • Сложность сохраняется на самом низком уровне (лучшее предложение для майнеров) за счет того, что блоки не штампуются раньше, чем они на самом деле появляются.

Взятые вместе, эти факторы говорят о том, что большинство блоков, созданных майнерами с небольшим хэшрейтом, которые не пытаются ничем манипулировать, будут довольно близки к точности. Однако для более мощного майнера тривиально манипулировать временными метками в течение коротких периодов времени , особенно если от этого можно что-то получить.

В конечном счете, нет криптографического способа проверить саму метку времени — только порядок определенных криптографических структур . Поэтому block.timestamp необходимо дополнить какой-либо другой стратегией в случае приложений с высокой ценностью / риском.

Во-первых, основное: использование строгого равенства == block.timestampнебезопасно, поскольку блок с такой точной отметкой времени может никогда не быть добыт. Так что используйте>= block.timestamp

Теперь это зависит от того, что произойдет, когда наступит «срок действия» контракта . По причинам, аналогичным безопасному использованию BLOCKHASH , block.timestampего следует безопасно использовать только в том случае, если общая сумма стоимости, основанная на том, что контракт делает в «время истечения срока действия», ниже, чем то, что майнер зарабатывает, добывая один блок. Если исход лотереи на миллионы зависит от block.timestamp, отметка времени, вероятно, будет изменена.

В «Желтой книге» нет ответа на вопрос «сколько он может быть отключен, прежде чем он будет отклонен другими узлами». Если block.timestampиспользуется, единственная гарантия (уравнение 43) состоит в том, что block.timestampона больше, чем у его родителя. Но есть теоретико-игровые причины, по которым block.timestampне будет существенной ошибки.

Из документации Solidity следует обратить внимание на следующее: вы публикуете транзакцию в момент времени X, эта транзакция содержит некоторый код, который вызывает block.timestampи включена в блок с отметкой времени Y, и этот блок включен в каноническую цепочку (опубликован) в момент времени X. время Z. Значение block.timestampбудет идентично Y, и X <= Y <= Z

Возможно, мне следует уточнить в своем ответе: у более крупных майнеров есть способы манипулировать временными метками, неся при этом меньшие затраты, чем стоимость вознаграждения за один блок. Таким образом, использование block.timestamp не может быть строго безопасным, если используются только низкие значения, как может быть случайность BLOCKHASH.
Я могу отредактировать или зачеркнуть свой ответ и указать, как более крупные майнеры могут манипулировать временными метками с низкими затратами... на что мне ссылаться?

Более безопасным решением было бы полагаться на block.number и расчетное время на приращение блока. Допустим, вы хотели создать договор аренды для контракта с определенной датой окончания. Вы можете рассчитать приблизительное время с помощью:

estimated_time_in_blocks = lease_length_in_seconds / average_block_time_in_seconds
lease_end_block_number = current_block + estimated_time_in_blocks

В договоре вы можете проверить:

block.number <= lease_end_block_number

Пример в Mastering Ethereum :

с 10-секундным временем блока 1 неделя соответствует примерно 60480 блокам. Таким образом, указание номера блока для изменения состояния контракта может быть более безопасным, поскольку майнеры не могут легко манипулировать номером блока.

Контракт BAT ICO использует этот подход