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

Что такое формальная проверка?

Формальная верификация — это процесс доказательства правильности системы или программы с использованием математических методов. Формальная верификация использует формальные методы, которые представляют собой математические методы для определения, проектирования и проверки систем. Методы формальной проверки могут доказать, что программа удовлетворяет заданной спецификации, или обнаружить ошибки или нарушения спецификации.

Подходы к формальной верификации в Solidity

Существует два основных подхода к формальной проверке в Solidity: проверка ограниченной модели и доказательство теорем.

1. Проверка ограниченной модели

Проверка ограниченной модели (BMC) — это метод, используемый для проверки правильности программы путем анализа ее поведения для конечного числа шагов. BMC проверяет, выполняется ли данное свойство для программы с фиксированным числом шагов выполнения. Свойство можно указать с помощью формулы темпоральной логики или утверждения в программе.

Одним из инструментов, используемых для BMC в Solidity, является средство проверки моделей на основе SMT Mythril. Mythril — это инструмент с открытым исходным кодом для анализа смарт-контрактов, в котором используется символическое выполнение, анализ испорченных данных и другие методы анализа смарт-контрактов. Mythril можно использовать для выполнения различных проверок безопасности, таких как обнаружение уязвимостей повторного входа, целочисленных переполнений и других потенциальных проблем безопасности.

Например, рассмотрим следующий код Solidity, реализующий простой контракт голосования:

contract Voting {
  mapping(address => bool) public hasVoted;
  uint public yesVotes;
  uint public noVotes;
  function vote(bool voteYes) public {
    require(!hasVoted[msg.sender]);
    if (voteYes) {
      yesVotes++;
    } else {
      noVotes++;
    }
    hasVoted[msg.sender] = true;
  }
}

Чтобы проверить правильность функции vote с помощью Mythril, мы можем использовать следующую команду:

$ myth analyze Voting.sol --execution-timeout 120

Эта команда проанализирует контракт Voting в течение 120 секунд и сообщит о любых потенциальных проблемах безопасности или уязвимостях. Mythril может обнаружить, что функция vote не имеет никаких проверок входных данных и может быть вызвана с недопустимыми входными данными, что может привести к переполнению или потере значимости переменных yesVotes и noVotes.

2. Доказательство теорем

Доказательство теорем — это метод, используемый для доказательства правильности программы путем построения математического доказательства того, что программа удовлетворяет заданной спецификации. Доказательство теорем включает ручное построение доказательства правильности с использованием языка формальных спецификаций, такого как Coq, Isabelle или HOL.

Одним из инструментов, используемых для доказательства теорем в Solidity, является платформа K. Платформа K — это формальная семантическая структура, которую можно использовать для определения и проверки языков программирования. Платформу K можно использовать для определения семантики Solidity и проверки ее программ с использованием методов доказательства теорем.

Например, рассмотрим следующий код Solidity, реализующий простой смарт-контракт для сложения двух целых чисел:

contract Adder {
  function add(uint a, uint b) public pure returns (uint) {
    uint c = a + b;
    return c;
  }
}

Чтобы проверить правильность функции add, используя K framework, мы можем определить формальную спецификацию функции, используя язык K. Спецификация K функции add может быть записана следующим образом:

rule <k> add(a:UInt, b:UInt) => c:UInt
  requires true
  ensures c == a + b
</k>

Эта спецификация K определяет правило, которое принимает два целых числа без знака a и b в качестве входных данных и возвращает их сумму c в качестве вывода. Правило указывает, что выход c равен сумме входов a и b. Мы можем использовать структуру K, чтобы проверить правильность функции add, доказав, что спецификация K функции удовлетворяется.

Чтобы доказать правильность функции add с помощью платформы K, мы можем использовать следующую команду:

$ kprove add.k

Эта команда будет использовать структуру K, чтобы доказать, что спецификация K функции add удовлетворяется, и вернет доказательство, если спецификация действительна.

Примеры формальной проверки в Solidity

Давайте рассмотрим несколько примеров формальной верификации в Solidity с использованием методов BMC и доказательства теорем.

Пример 1: Обнаружение уязвимостей повторного входа с помощью Mythril

Повторный вход — это уязвимость безопасности, которая может возникнуть в смарт-контрактах, когда функция может быть вызвана несколько раз до того, как ее предыдущее выполнение будет завершено. Повторный вход может позволить злоумышленнику манипулировать состоянием контракта и украсть средства или активы из контракта.

Чтобы обнаружить уязвимости повторного входа в Solidity, мы можем использовать символьный механизм выполнения Mythril. Механизм символического исполнения Mythril может отслеживать пути выполнения смарт-контракта и обнаруживать потенциальные уязвимости повторного входа.

Рассмотрим следующий код Solidity, реализующий простой банковский контракт:

contract Bank {
  mapping(address => uint) public balances;
  function deposit() public payable {
    balances[msg.sender] += msg.value;
  }
  function withdraw(uint amount) public {
    require(amount <= balances[msg.sender]);
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success);
    balances[msg.sender] -= amount;
  }
}

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

$ myth analyze Bank.sol --execution-timeout 120 --truffle

Эта команда проанализирует контракт Bank с помощью механизма символического исполнения Mythril и сообщит о любых потенциальных уязвимостях повторного входа или проблемах безопасности.

Пример 2: Проверка смарт-контракта с использованием K Framework

Мы можем использовать фреймворк K для проверки корректности смарт-контрактов, написанных в Solidity. Платформу K можно использовать для определения семантики Solidity и проверки ее программ с использованием методов доказательства теорем.

Рассмотрим следующий код Solidity, реализующий простой контракт голосования:

contract Voting {
  mapping(address => bool) public hasVoted;
  uint public yesVotes;
  uint public noVotes;
  function vote(bool voteYes) public {
    require(!hasVoted[msg.sender]);
    if (voteYes) {
      yesVotes++;
    } else {
      noVotes++;
    }
    hasVoted[msg.sender] = true;
  }
}

Мы можем использовать структуру K для проверки правильности функции vote в этом контракте, определив спецификацию K функции и доказав, что спецификация удовлетворяется.

Спецификация K функции vote может быть записана следующим образом:

rule <k> vote(hv:Map, yv:UInt, nv:UInt, v:Address, b:Bool) => hv':Map, yv':UInt, nv':UInt
  requires !hv

Эта спецификация K определяет правило, которое принимает четыре входа: отображение hv, которое представляет набор адресов, которые уже проголосовали, два целых числа без знака yv и nv, которые представляют количество голосов «за» и «против» соответственно, и логическое значение значение b, которое представляет голос текущего избирателя. Правило возвращает три результата: новое сопоставление hv', включающее текущий адрес избирателя, и два обновленных целых числа без знака yv' и nv', представляющих обновленное количество голосов «за» и «против» соответственно. Правило указывает, что выходные данные hv' включают текущий адрес избирателя, а выходные данные yv' и nv' обновляются на основе текущего голоса избирателя.

Мы можем использовать структуру K, чтобы доказать, что спецификация K функции vote удовлетворяется реализацией этой функции в Solidity. Для этого мы можем использовать следующую команду:

$ kprove vote.k

Эта команда будет использовать структуру K, чтобы доказать, что спецификация K функции vote удовлетворяется реализацией функции Solidity, и вернет доказательство, если спецификация действительна.

Заключительные слова

Формальная проверка — важный метод обеспечения правильности и безопасности смарт-контрактов. Используя методы формальной проверки, такие как проверка ограниченной модели и доказательство теорем, мы можем обнаруживать и предотвращать уязвимости безопасности в смарт-контрактах и ​​обеспечивать их правильное поведение. Solidity предлагает различные инструменты и фреймворки, которые упрощают применение методов формальной проверки к смарт-контрактам, включая Mythril и фреймворк K. Используя эти инструменты и фреймворки, вы можете создавать более безопасные и надежные смарт-контракты, менее подверженные атакам.

Если вы нашли эту статью информативной и полезной, подпишитесь на меня, чтобы получать больше материалов, связанных с блокчейном и криптовалютой. Вы также можете подписаться на мою рассылку, чтобы получать новости о моих последних статьях и проектах.

Новичок в трейдинге? Попробуйте криптотрейдинговые боты или копи-трейдинг на лучших криптобиржах

Присоединяйтесь к Coinmonks Telegram Channel и Youtube Channel и получайте ежедневные Крипто новости

Также читайте