Взгляните на библиотеку SafeMath от OpenZeppelin

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

«Арифметические операции в Solidity переносятся при переполнении. Это может легко привести к ошибкам, потому что программисты обычно предполагают, что переполнение вызывает ошибку, что является стандартным поведением для языков программирования высокого уровня. SafeMath восстанавливает эту интуицию, отменяя транзакцию при переполнении.

Использование этой библиотеки вместо непроверенных операций устраняет целый класс ошибок, поэтому рекомендуется использовать ее всегда ». - Документы OpenZeppelin

«Операции в Solidity обернуть при переполнении» относятся к определенной вещи, привязанной к способу представления чисел в компьютерах и, в частности, в Solidity.

В следующем смарт-контракте я реализовал простой метод проверки переполнения и переполнения (как обычно, прямо в Ремиксе):

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

Обратите внимание, как я использовал int8 в качестве типа ввода и вывода методов. Это позволит мне быстро описать реализацию.

На предыдущем рисунке вы видите то, что означает предложение «операции в Solidity переносятся при переполнении». А теперь представьте, что uint8, с которым мы возились, представляет собой количество каких-то ценных активов. Это просто означает, что ваша система будет прекрасно работать в большинстве случаев (приращения и убывания далеко от пределов представления) и резко выйдет из строя, создав несогласованное состояние.

На данный момент ясно, что нам действительно нужна более безопасная математика - даже в простейшем смарт-контракте.

Давайте теперь посмотрим, как работает предыдущий пример, используя SafeMath для увеличения / уменьшения.

SafeMath предоставляется OpenZeppelin для uint256. Это означает, что он никогда не переполнится нашим примером, в котором используется uint8. Например, вы должны переполнить, если передадите 255, но этого не произойдет, потому что в SafeMath он будет представлен как uint256.

Для ясности я «разработал» uint8 версию SafeMath, просто заменив uint256 на uint8 в исходном SafeMath. И я назвал это SafeMath8:

Вы можете использовать его прямо в Remix и импортировать, как показано в следующем примере:

Как вы могли заметить, мы просим Solidity «прикрепить» методы, определенные в SafeMath8, к uint8. Таким образом, нам разрешено вызывать методы sub() и add(), которые представляют новый, более безопасный способ вычитания и добавления двух целых чисел без знака.

На следующем рисунке показано, что вы получаете, вызывая два метода с параметрами для получения переполнения / потери значимости:

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

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

Заключение

SafeMath (и SafeMath8) - это фундамент, на котором можно построить безопасный смарт-контракт. Это особенно важно, учитывая, что вы обычно будете иметь дело с активами, которые (надеюсь) будут стоить сотни фиатных монет.