Насколько безопасно использовать block.timestamp в качестве времени истечения контракта? Если майнер предоставляет неправильную временную метку в заголовке блока, сколько времени она может быть отключена, прежде чем она будет отклонена другими узлами? Есть ли стратегия сделать контракт более устойчивым к этому?
Не особенно , но это зависит от варианта использования.
Время блока зависит от следующих ограничений:
Взятые вместе, эти факторы говорят о том, что большинство блоков, созданных майнерами с небольшим хэшрейтом, которые не пытаются ничем манипулировать, будут довольно близки к точности. Однако для более мощного майнера тривиально манипулировать временными метками в течение коротких периодов времени , особенно если от этого можно что-то получить.
В конечном счете, нет криптографического способа проверить саму метку времени — только порядок определенных криптографических структур . Поэтому 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.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 использует этот подход
Джефф Коулман
эт