Смарт-контракты на Solidity
Как мы уже говорили в начале, в Ethereum существует два различных типа аккаунтов:
- аккаунты принадлежащие внешним пользователям (EOA)
- аккаунты смарт-контрактов (аккаунт СмК)
EOA контролируются пользователями, часто с помощью программного обеспечения, например, приложения-кошелька, которое является внешним по отношению к платформе Ethereum. В отличие от Аккаунты СмК контролируются программным кодом, который выполняется виртуальной машиной Ethereum. Одним словом, EOA - это простые аккаунты без какого-либо связанного кода или хранилища данных, в то время как аккаунты СмК имеют связанный код и хранилище данных. EOA контролируются транзакциями, созданными и криптографически подписанными закрытым ключом в "реальном мире", внешнем по отношению к протоколу и независимом от него, в то время как аккаунты СмК не имеют закрытых ключей и поэтому "контролируют себя" заранее определенным образом, предопредлённым кодом. Оба типа аккаунтов идентифицируются адресом Ethereum. В этой главе мы рассмотрим аккаунт смарт-контракта и программный код, который ими управляет.
Что такое смарт-контракт?
Термин "смарт-контракт" на протяжении многих лет использовался для описания самых разных вещей. В 1990-х годах криптограф Ник Сабо придумал этот термин и определил его как "набор обещаний, указанных в цифровой форме, включая протоколы, в рамках которых стороны выполняют другие обещания". С тех пор концепция СмК развивалась, особенно после появления децентрализованных блокчейн-платформ с изобретением Bitcoin в 2009 году. В контексте Ethereum этот термин на самом деле является немного неправильным, учитывая, что смарт-контракты Ethereum не являются ни смарт-контрактами, ни юридическими контрактами, но термин прижился. Мы используем термин "смарт-контракты" для обозначения неизменяемых компьютерных программ, которые детерминированно выполняются в контексте виртуальной машины Ethereum как части сетевого протокола Ethereum - то есть на децентрализованном мировом компьютере Ethereum.
Давайте уточним это определение:
Компьютерные программы
Смарт-контракты - это просто компьютерные программы сохраненные в БД блокчейна. Слово "контракт" не имеет юридического значения в данном контексте.
Неизменный
После развертывания код смарт-контракта не может быть изменен, в отличие от традиционного программного обеспечения. Единственный способ изменить смарт-контракт - это развернуть новый смарт-контракт.
Детерминированный
Результат выполнения смарт-контракта одинаков для всех, кто его запускает, с учетом контекста транзакции, инициировавшей его выполнение, и состояния блокчейна Ethereum в момент выполнения.
Контекст EVM
Смарт-контракты работают с очень ограниченным контекстом исполнения. Они могут получить доступ к собственному состоянию, контексту транзакции, которая их вызвала, и некоторой информации о последних блоках.
Децентрализованный всемирный компьютер
EVM работает на каждом узле Ethereum, но поскольку все экземпляры EVM работают с одним и тем же начальным состоянием и создают одно и то же конечное состояние, система в целом работает как единый "мировой компьютер".
Жизненный цикл смарт-контракта
Смарт-контракты обычно пишутся на языке высокого уровня, таком как Solidity. Но для запуска их необходимо скомпилировать в низкоуровневый байткод, который выполняется в EVM. После компиляции они развертываются на платформе Ethereum с помощью специальной транзакции по созданию контракта, которая идентифицируется как таковая путем отправки на специальный адрес создания контракта, а именно 0x0 (см. [contract_reg]). Каждый контракт идентифицируется Ethereum-адресом, который формируется из транзакции создания контракта как функция аккаунта-источника и nonce. Ethereum-адрес контракта может быть использован в транзакции в качестве получателя, отправляя средства на контракт или вызывая одну из функций контракта. Обратите внимание, что, в отличие от EOA, не существует ключей, связанных с аккаунтом, созданным для нового смарт-контракта. Как создатель контракта, вы не получаете никаких особых привилегий на уровне протокола (хотя вы можете явно прописать их в смарт-контракте). Вы, конечно, не получаете закрытый ключ для аккаунта контракта, которого на самом деле не существует - мы можем сказать, что аккаунты смарт-контрактов владеют сами собой.
Важно отметить, что контракты выполняются только в том случае, если они вызваны транзакцией. Все смарт-контракты в Ethereum выполняются, в конечном счете, благодаря транзакции, инициированной из EOA. Контракт может вызвать другой контракт, который может вызвать другой контракт, и так далее, но первый контракт в такой цепочке выполнения всегда будет вызван транзакцией из EOA. Контракты никогда не выполняются "сами по себе" или "в фоновом режиме". Контракты фактически находятся в спящем состоянии до тех пор, пока транзакция не инициирует их выполнение, прямо или косвенно, как часть цепочки вызовов контрактов. Стоит также отметить, что смарт-контракты не выполняются "параллельно" ни в каком смысле - компьютер Ethereum можно считать однопоточной машиной.
Транзакции атомарны, они либо успешно завершаются, либо отменяются. Успешное завершение транзакции означает разные вещи при разных сценариях:
-
если транзакция отправляется из EOA в другой EOA, то любые изменения в глобальном состоянии (например, остатки на аккаунтах), сделанные транзакцией, записываются;
-
если транзакция отправляется из EOA в контракт, который не вызывает никаких других контрактов, то любые изменения в глобальном состоянии записываются (например.например, остатки на аккаунтах, переменные состояния контрактов)
-
если транзакция отправляется от EOA к контракту, который вызывает другие контракты только таким образом, что распространяет ошибки, то любые изменения глобального состояния записываются (например, остатки на аккаунтах, переменные состояния контрактов).например, остатки на аккаунтах, переменные состояния контрактов); и
-
если транзакция отправляется из EOA в контракт, который вызывает другие контракты способом, который не распространяет ошибки, то могут быть записаны только некоторые изменения глобального состояния (например, остатки на аккаунтах, переменные состояния не ошибающихся контрактов), тогда как другие изменения глобального состояния не записываются (например, переменные состояния ошибающихся контрактов). В противном случае, если транзакция отменяется, все ее последствия (изменения в состоянии) "откатываются", как если бы транзакция никогда не выполнялась. Неудавшаяся транзакция все равно записывается как попытка, и эфир, потраченный на газ для ее выполнения, списывается со аккаунта создателя, но в остальном она не имеет никаких других эффектов на состояние контракта или аккаунта.
Как уже упоминалось ранее, важно помнить, что код контракта не может быть изменен. Однако контракт можно "удалить", удалив код и его внутреннее состояние (хранилище) из его адреса, оставив пустой аккаунт. Любые транзакции, отправленные на этот адрес аккаунта после удаления контракта, не приводят к выполнению кода, поскольку там больше нет кода для выполнения. Чтобы удалить контракт, вы выполняете операционный код EVM под названием SELFDESTRUCT (ранее называвшийся SUICIDE).
Эта операция стоит "отрицательный газ", возврат газа, тем самым стимулируя освобождение ресурсов клиента сети от удаления сохраненного состояния
Удаление контракта таким образом не приводит к удалению истории транзакций (прошлого) контракта, поскольку сам блокчейн неизменяем. Важно также отметить, что возможность SELFDESTRUCT будет доступна только в том случае, если автор контракта запрограммировал смарт-контракт на такую функциональность. Если в коде контракта отсутствует опкод SELFDESTRUCT или он недоступен, смарт-контракт не может быть удален.