Reino: Time and State

A computação distribuída consiste em tempo e estado. Isto é, para que mais de um componente se comunique, é necessário compartilhar o estado, o que exige tempo.

A maioria dos programadores antropomorfiza seu trabalho. Eles enxergam um thread de controle executando todo o programa da mesma forma como enxergariam a si mesmos fazendo o trabalho inteiro por conta própria. Computadores modernos, entretanto, alternam entre tarefas com muita rapidez e, em sistemas multi-core, multi-CPU ou distribuídos, dois eventos podem ocorrer exatamente ao mesmo tempo. Defeitos rapidamente são postos nas lacunas entre o modelo do programador de como um programa é executado e o que ocorre na realidade. Esses defeitos estão relacionados com interações inesperadas entre threads, processos, tempo e informações. Essas interações ocorrem por meio de estados compartilhados: semáforos, variáveis, o sistema de arquivos e, basicamente, todas as coisas capazes de armazenar informações.

Often Misused: Block Values

Abstract
Uma função usa block.timestamp ou block.number como um proxy para o tempo.
Explanation
Valores associados a block.timestamp ou block.number são frequentemente usados por desenvolvedores para acionar eventos dependentes de tempo, no entanto, esses valores geralmente dão uma noção de tempo que geralmente não é segura para uso.

Devido à natureza descentralizada do blockchain, os nós podem sincronizar o tempo apenas até certo ponto. Na melhor das hipóteses, usar block.timestamp não é confiável e, na pior das hipóteses, mineradores mal-intencionados poderão alterar o carimbo de data/hora de seus blocos se perceberem uma vantagem em fazê-lo.

Quanto a block.number, embora seja possível prever o tempo entre os blocos (aproximadamente 14 segundos), os tempos dos blocos não são constantes e podem variar dependendo da atividade da rede. Isso torna block.number não confiável para cálculos relacionados ao tempo.

Exemplo 1: O código a seguir usa block.number para desbloquear fundos após um determinado período.


function withdraw() public {
require(users[msg.sender].amount > 0, 'no amount locked');
require(block.number >= users[msg.sender].unlockBlock, 'lock period not over');
uint amount = users[msg.sender].amount;
users[msg.sender].amount = 0;
(bool success, ) = msg.sender.call.value(amount)("");
require(success, 'transfer failed');
}
References
[1] Enterprise Ethereum Alliance Don't misuse block data
[2] Standards Mapping - CIS Azure Kubernetes Service Benchmark 2.0
[3] Standards Mapping - CIS Amazon Elastic Kubernetes Service Benchmark 2.0
[4] Standards Mapping - CIS Amazon Web Services Foundations Benchmark 3
[5] Standards Mapping - CIS Google Kubernetes Engine Benchmark normal
[6] Standards Mapping - Smart Contract Weakness Classification SWC-116
desc.structural.solidity.swc116