Как переливы работают в солидности?

Я только что закончил Token Level в Zeppelin's Ethernaut , и в конце они объяснили, что переполнения очень распространены в солидности. Я даже не думал о переливах, я просто пытался украсть токены.

Это код, который они показывают:


Переполнения очень распространены в солидности и должны быть проверены с помощью управляющих операторов, таких как:

if(a + c > a) {
a = a + c;
}

Более простой альтернативой является использование библиотеки OpenZeppelin SafeMath, которая автоматически проверяет наличие переполнения во всех математических операторах. Результирующий код выглядит следующим образом:

 a = a.add(c);

Если есть переполнение, код вернется.


Я просто не могу понять, что такое переполнение в солидности, может кто-нибудь объяснить мне новичку, что это такое, или указать мне статью, где посмотреть. Спасибо!

Ответы (2)

Из https://programtheblockchain.com/posts/2018/04/27/avoiding-integer-overflows-safemath-isnt-enough/ :

Целые числа фиксированного размера имеют диапазон значений, которые они могут представлять. Например, 8-битное целое число без знака может хранить значения от 0 до 255 (2^8-1). Когда результат некоторых арифметических операций выходит за пределы поддерживаемого диапазона, возникает целочисленное переполнение . В виртуальной машине Ethereum (EVM) следствием целочисленного переполнения является потеря старших битов результата. Например, при работе с 8-битными целыми числами без знака 255 + 1 = 0. Это легче увидеть в двоичном формате, где 1111 1111 + 0000 0001должно быть 1 0000 0000, но поскольку доступно только 8 бит, самый левый бит теряется, что приводит к значению 0000 0000.

Интуитивно эффект целочисленного переполнения можно рассматривать как «обтекание» значения.

Большое спасибо @smarx, отличная статья, как раз то, что мне было нужно

Переполнение — это когда результат бинарной операции (т. е. операции с двумя операндами) не соответствует типу операндов (большему типу, если они не идентичны).

Например:

uint8 a = 43;
uint16 b = 65500;
uint32 c = a + b;

В приведенном выше коде результатом должно быть cзначение 65543.

Тип cможет правильно представлять это значение, но результат a + bвычисляется в uint16(более крупный тип aи b), который не может правильно представить это значение.