Надежность в простых шагах: как создать смарт-контракт условного депонирования (часть 1)
19 мая 2022 г.Вступление
Изучение нового языка программирования сопряжено с некоторыми проблемами, которые могут включать в себя: принятие решения о том, стоит ли изучать язык программирования в первую очередь; распределение времени; и, что самое трудное, настойчивость перед лицом других обязанностей. Это факт, что обучение путем создания интересующего проекта может быть лучшей мотивацией для продолжения обучения, даже когда необходимо уделить внимание другим вещам.
Привет! Это первая статья из серии, в которой мы будем изучать Solidity in Easy Steps. Мы создадим контракт для двух деловых партнеров, которые не доверяют друг другу 🤣🤣. Первый не доверяет второму доставить его задачу или товар после оплаты, а второй не доверяет первому заплатить после выполнения его части сделки... 😳😳Звучит знакомо?
Таким образом, мы предлагаем договор условного депонирования.
Ожидания
В этой статье мы создадим смарт-контракт условного депонирования, используя Solidity с фиктивным объяснением для каждой строки кода. Читателям рекомендуется вручную вводить предоставленные коды. Прежде чем мы приступим к делу, давайте посмотрим, что от вас ожидается, чтобы мы могли быть на одной волне.
Предположение: у вас есть базовые знания о Solidity и программировании в целом.
Сложность: 1/10 (Начинающий)
Время программирования: 5 мин.
К концу этой статьи читатели должны понять:
- Как составить простую диаграмму классов для контрактов
- Различные типы комментариев в языке программирования Solidity
- Основы Remix IDE
- Как создавать простые смарт-контракты
- Как создавать функции в Solidity
- Ключевые слова Solidity «public», «payable», «view» и «this».
- Глобальная переменная Solidity
msg
Функции, которые необходимо реализовать
В этой версии нам придется подниматься по лестнице функций поэтапно:
- Спонсор должен быть в состоянии финансировать контракт
- Спонсор должен указать адрес единственного бенефициара
- Бенефициар или кто-либо другой должен быть в состоянии проверить, что контракт был профинансирован на согласованную сумму
- Бенефициар должен иметь возможность видеть, кто был назначен бенефициаром
- Плательщик должен иметь возможность выдать средства только получателю
Диаграмма классов
Анализируя или кодируя приложение, профессионалы начинают с дизайна (например, диаграммы классов). Хотя на данном этапе это и не обязательно, полезно привыкнуть к хорошим практикам, поэтому мы собираемся создать минималистическую диаграмму классов только для концептуализации.
Какая, к черту, диаграмма классов??? Проще говоря, диаграмма классов — это графическое представление системы. Актуальная диаграмма классов позволяет любому, включая вас в будущем, получить представление обо всем контракте. Как правило, на диаграмме классов контракта перечислены переменные, функции и события в контракте.
Переменные
В этой версии нам понадобятся две переменные, а именно:
- спонсор: Плательщик. Каждый должен иметь возможность проверить, кто вложил средства. Поскольку пользователи блокчейна могут быть анонимными, как нам узнать спонсора? Им создать имя пользователя? Нет!!! Вместо этого мы можем отследить адрес кошелька, который использовался для финансирования контракта.
- бенефициар: предполагаемый получатель. Опять же, каждый должен иметь возможность убедиться в этом. По крайней мере, бенефициар будет уверен, что средства заблокированы для него.
Функции
Для этой версии нам понадобятся следующие функции:
- fund: Эта функция будет вызвана спонсором с суммой для блокировки и предполагаемым бенефициаром, для которого она предназначена.
- выпуск: Эта функция вызывается спонсором, когда он готов передать средства бенефициару. Обратите внимание, что нам не нужен сценарий, при котором бенефициар сможет высвободить средства для себя.
- getBalance: Эта функция должна быть доступна любому, чтобы проверить фактическую сумму, заблокированную в контракте. Функция, которая не делает ничего, кроме получения текущего значения переменной, такой как эта, называется функцией-получателем. Таким образом, наш контракт можно изобразить так, как показано ниже:
Настройка разработки
Ничего скачивать не нужно... Что???? Странно для сеанса программирования...
На этом занятии мы будем использовать веб-платформу разработки Solidity под названием Remix. Его можно использовать бесплатно, зайдя на https://remix.ethereum.org/. Вы можете узнать больше об этой замечательной платформе, прочитав ее [документацию] (https://remix-ide.readthedocs.io/en/latest/).
Теперь, чтобы настроить нашу среду разработки:
- Посетите веб-сайт ремиксов https://remix.ethereum.org/
- После загрузки Remix создайте новый файл с именем «Escrow.sol», как показано ниже.
Кодирование и объяснение
Далее приводится полный [код для этой версии] (https://gist.github.com/EwetoyeIbrahim/edd2011cd0e8df830b489323acd0ade5), за которым следует подробное пояснение на основе строк. Объясняя строки кода, мы коснемся различных аспектов Solidity, так что читайте дальше!!! Введите приведенные ниже строки в файл Escrow.sol, созданный выше, далее следует объяснение.
Этот код можно разветвить в [этом github gist] (https://gist.github.com/EwetoyeIbrahim/edd2011cd0e8df830b489323acd0ade5).
```javascript
// SPDX-идентификатор лицензии: MIT
прочность прагмы >=0,7,0 <0,9,0;
- @title EscrowSol
- @dev Управляет переводами средств между двумя сторонами
контракт EscrowSol {
// Адрес кошелька плательщика
адрес общественного спонсора;
// Адрес кошелька предполагаемого получателя
адрес государственного бенефициара;
/// Блокировка определенного криптографического значения.
/// @param counter адрес предполагаемого получателя
/// @dev блокировка криптографии для контрагента
функция фонд(адрес контрагента) государственная кредиторская задолженность {
бенефициар = контрагент;
спонсор = msg.sender;
/// Освобождаем все заблокированные средства.
/// @dev Сделка совершена, пусть только плательщик выпустит средства.
функция release() общедоступная платежная {
если (msg.sender==спонсор){
// Перечислить все средства получателю
подлежащий оплате(получатель).перевод(адрес(этот).баланс);
/// Вернуть заблокированное значение.
/// @dev любой должен иметь возможность увидеть действительно заблокированное значение crpto.
/// @вернуть криптографическое значение
функция getBalance() публичного представления возвращает (uint) {
обратный адрес(этот).баланс;
Линия 1
// SPDX-идентификатор лицензии: MIT
Информационная строка для обозначения типа лицензии всего кода, содержащегося в конкретном файле.
Строка 3
```javascript
прочность прагмы >=0,7,0 <0,9,0;
Привет, солидность, запусти этот файл, используя любую из твоих версий от 0.7.0 до 0.9.0. Обратите внимание, что, в отличие от строки 1, эта строка заканчивается точкой с запятой.
В Solidity все строки, которые не заканчиваются скобками, фигурными скобками или круглыми скобками, должны заканчиваться точкой с запятой.
Строки 5–8
```javascript
- @title EscrowSol
- @dev Управляет переводами средств между двумя сторонами
Группа комментариев специального типа под названием NatSpec (Естественные спецификации). Они полезны для автоматического создания пользовательской документации. Чем NatSpec отличаются от обычных многострочных комментариев??? Помимо жаргона, достаточно знать, что, как правило, комментарии могут служить трем целям:
- Сообщите лицензию на код (если она присутствует, обычно это первая строка?)
- Объяснять строки кодов в программе только тем, кто имеет доступ к исходному коду.
- Разделы кодов документов, это многострочные комментарии с некоторыми поддерживаемыми тегами (такими как
@title
), которые называютсяNatSpec
ы. Они могут быть автоматически скомпилированы для использования в качестве документации к программе.
Вернемся к объяснению кода, здесь мы объявляем заголовок с помощью @title
и однострочное описание контракта с помощью @dev
Строка 9
```javascript
контракт EscrowSol { //} Закрыт в строке 38
Мы обозначаем начало нашего контракта под названием «EscrowSol», и все, что находится в круглых скобках в этой строке и ее закрывающем аналоге, будет рассматриваться Solidity как часть этого контракта. Зачем обозначать начало контракта, ведь солидность нужна для написания контрактов? Что ж, в файл можно поместить более одного контракта, поэтому все элементы, принадлежащие контракту, если они не импортированы, должны быть заключены в круглые скобки контракта.
Строка 11
```javascript
// Адрес кошелька плательщика
адрес общественного спонсора;
Нам нужно знать спонсора, и поскольку мы хотим, чтобы любой мог получить доступ к адресу спонсора, мы добавили ключевое слово «public» в Solidity для достижения этой цели.
Всякий раз, когда переменная назначается общедоступной, Solidity определяет функцию автоматического получения, которая позволяет миру видеть текущее значение переменной. Таким образом, мы сэкономили несколько нажатий клавиш на приготовление геттерной функции.
Строка 13
```javascript
// Адрес кошелька предполагаемого получателя
адрес государственного бенефициара;
То же объяснение, что и в строке 11, но теперь для получателя.
Строки 15–17
```javascript
/// Блокировка определенного криптографического значения.
/// @param counter адрес предполагаемого получателя
/// @dev блокировка криптографии для контрагента
NatSpecs для функции fund, которую мы собираемся написать. Обратите внимание, что предыдущая NatSpec была заключена в «/» и «/», а на этот раз мы использовали «///» в каждой строке.
Что ж, это способ сообщить вам о другом способе достижения этого в Solidity. Напомним, что мы хотим, чтобы спонсор указал предполагаемого бенефициара во время финансирования, поэтому единственный параметр, который нам нужно передать этой функции. Теперь это явно указано в NatSpec с использованием @param
, который здесь является единственным новым тегом.
Строка 18
```javascript
function fund(адрес контрагента) public payable { //Закрыто в строке 21
Как правило, в Solidity функция определяется с помощью ключевого слова «функция», присваивается ей имя, аргументы (если есть) и их типы заключаются в квадратные скобки, за которыми следуют декораторы/модификаторы (если есть), и, наконец, за ними следуют круглые скобки, которые инкапсулировать коды, которые будут выполняться при вызове.
Поэтому в строке 18 мы определили функцию с именем fund
, которая принимает адрес получателя в качестве аргумента с именем counterpart
, украшенного ключевым словом Solidity public, чтобы его можно было выполнять из любого места, а также снабженного payable
для платежа в контракт, подлежащий обработке.
Что, черт возьми, `оплачивается
??? Не вдаваясь в подробности, всякий раз, когда криптовалюта должна быть переведена, адрес или функция (как в этом случае) должны быть сделаны «оплачиваемыми», иначе фактическая передача монет никогда не состоится.
Строка 19
```javascript
бенефициар = контрагент;
Мы устанавливаем адрес бенефициара на аналогичный адрес, предоставленный спонсором.
Строка 20
```javascript
спонсор = msg.sender;
) // Конец функции фонда
Мы устанавливаем адрес спонсора с помощью msg.sender
Надеюсь, вы не спрашиваете, что такое msg
?
При вызове контракта Solidity по умолчанию передает некоторые глобальные переменные, в том числе msg
, которые обладают свойствами, которые можно использовать для предоставления информации о цепочке блоков. msg предоставляет такую информацию, как публичный адрес, вызвавший текущую операцию (msg.address), отправленную сумму (msg.value) и оставшуюся стоимость выполнения операции блокчейна (msg.gas). ).
Строка 25
```javascript
функция release() общедоступная платежная {
Мы вводим оплачиваемую функцию под названием release.
Строки 26–29
```javascript
если (msg.sender==спонсор){
// Перечислить все средства получателю
подлежащий оплате(получатель).перевод(адрес(этот).баланс);
} // Конец функции выпуска
Мы гарантируем, что человек, вызывающий эту функцию, является спонсором, после чего мы переводим все средства, заблокированные в смарт-контракте, бенефициару.
Строки 35–37
```javascript
функция getBalance() публичного представления возвращает (uint) {
обратный адрес(этот).баланс;
} // Конец контракта
Теперь мы создаем функцию с именем getBalance
, которая позволит нам получить стоимость средств в нашем контракте. В процессе мы вводим два новых ключевых слова («view» и «this»).
Ключевое слово view
используется для обозначения того, что функции не должно быть разрешено вносить какие-либо изменения в состояние контракта в блокчейне, хотя мы все еще хотим иметь возможность читать состояние контракта. Если нам также не нужно читать какие-либо свойства состояния, мы могли бы вместо этого использовать ключевое слово pure
.
Здесь мы получили доступ к балансу контракта через ключевое слово this.
Ключевое слово this
указывает на текущий работающий контракт и все, что может быть достигнуто через него. В нашем случае нас просто волнует его балансовое свойство.
Эй!!!! Пришло время привести наш контракт в действие. Сохраните его, если вы еще этого не сделали.
Запуск нашего договора условного депонирования
Remix оснащен виртуальной машиной JavaScript, которая имитирует блокчейн, что позволяет легко тестировать смарт-контракты на ходу в браузере. Посмотрите на гифку ниже, сначала нам нужно скомпилировать (в основном это делается автоматически, если не возникла ошибка), а затем развернуть наш смарт-контракт.
Обратите внимание, что после развертывания мы нажимаем на имя контракта ниже, чтобы открыть постоянно доступные переменные и функции контракта. Также обратите внимание, что некоторые кнопки окрашены в синий цвет, а некоторые — в красный.
В Remix «оплачиваемые» функции (функции, способные передавать значения между аккаунтами) окрашены в красный цвет. просмотр
или чистые
функции (функции, которые не вызывают никаких изменений в состоянии контракта, но возвращают значение, хранящееся в контракте) окрашены в синий цвет.
По умолчанию Remix JavaScript VM предоставляет некоторые адреса и поддельные эфиры для выполнения нашего контракта. В этом случае мы будем считать, что вторая учетная запись является спонсором, а третья учетная запись — бенефициаром.
Тем не менее, давайте выполним некоторые операции, после которых вы можете поиграть с контрактом по своему усмотрению. Ниже показана иллюстрация в формате gif, за которой следует список шагов, предпринятых для запуска контракта.
- Нажмите на кнопки бенефициар, спонсор и получить сумму, чтобы убедиться, что они в настоящее время пусты.
- Выберите третий счет, который мы намерены использовать в качестве получателя, и скопируйте адрес.
- Выберите второй аккаунт, который мы хотим использовать в качестве спонсора.
- Введите сумму для финансирования контракта в поле значения. Предположим, мы хотим финансировать контракт с помощью 1Ether.
- Перейдите к кнопке пополнения, вставьте адрес получателя, скопированный на шаге 2, и нажмите пополнить. Обратите внимание, что стоимость была вычтена из нашего эфирного баланса.
- Нажмите на кнопки бенефициар, спонсор и получить сумму, чтобы убедиться, что значения были обновлены.
Перейдите на любой из оставшихся аккаунтов (чужой) и попробуйте разблокировать фонд, нажав на кнопку разблокировки. Проверьте баланс еще раз, чтобы убедиться, что он был успешно снят. Обратите внимание, что сумма все еще остается в контракте, это результат строки 26 нашего кода, которая гарантирует, что только спонсор имеет право на освобождение.
- Теперь измените учетную запись обратно на учетную запись спонсора.
- Нажмите отпустить.
- Нажмите getBalance, чтобы убедиться, что фонд был переведен из контракта в пользу бенефициара. Вы можете подтвердить, что он ушел на адрес получателя, проверив количество эфира на третьем счете.
Отличная работа!!!! Вы разработали первую версию смарт-контракта на блокчейне в Solidity.
Области для дальнейшего улучшения
Давайте теперь взглянем на возможности для дальнейшего развития, которые мы рассмотрим в следующей статье этой серии.
- Проблема 1: спонсор обязан предоставить бенефициару во время финансирования контракта, или спонсор может добавить больше средств в контракт. Это хорошая функция, особенно когда у сторон есть другие соглашения, например, спонсор должен финансировать условное депонирование на поэтапной основе или стороны соглашаются увеличить рассматриваемую сумму. Проблема с текущей реализацией заключается в том, что если спонсор хочет быть мошенником, после завершения задачи он может снова вызвать функцию фонда и передать адрес своей невесты в качестве бенефициара. Это в конечном итоге переведет фонд их жениху 🥺. Таким образом, в следующем посте мы по-прежнему сохраним несколько вариантов финансирования, но не будем обновлять учетную запись получателя.
- Проблема 2: Текущая реализация не требует посредников. А если возникнет спор? Что ж, если мы исправим проблему безопасности выше, средства останутся в контракте навсегда, пока не будут освобождены спонсором. Таким образом, Мы вводим доверенную сторону (например, одноранговую торговую платформу), которая управляет контрактом (вместо любой из сторон) и будет иметь право только в случае спора, разблокировать или вернуть средства.
Эти среди других вопросов будут решаться в следующем посте этой серии.
Пойду готовить!!!
Также читайте [здесь] (https://blog.mathsend.com/solidity-in-easy-steps-building-an-escrow-smart-contract-part-1).
Оригинал