Кодирование функции PayNow с помощью Solidity: 3 метода смарт-контрактов, которые необходимо знать

Кодирование функции PayNow с помощью Solidity: 3 метода смарт-контрактов, которые необходимо знать

26 апреля 2022 г.

Вступление


Экономика web3 находится на подъеме, и сейчас самое подходящее время для изучения этой технологии. Вы не можете позволить себе упустить этот глобальный спрос на разработчиков web3, о котором я так взволнован.


Согласно этому веб-сайту, средняя зарплата разработчика блокчейна составляет около 146 250$ в год, что является самым высоким показателем по сравнению с другой разработкой программного обеспечения. карьера.


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


Как начать? Вы можете спросить, вы делаете это, создавая одно dApp за раз. Свяжитесь со мной, если вам нужно частное обучение по разработке блокчейна.


Теперь давайте перейдем к сути этого урока…


Почему вы должны освоить обработку платежей в Solidity


Язык программирования блокчейна, такой как Solidity, — это язык программирования, созданный для обработки денег. Они созданы, чтобы революционизировать способы ведения бизнеса в Интернете. Чего не скажешь о других языках программирования, таких как Java, C++, PHP и т. д.


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


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


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


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


В этом руководстве вы узнаете о трех функциях, которые помогут вам перевести деньги с одного счета на другой, и о рекомендуемом для вас методе. Давайте посмотрим на этот пример смарт-контракта ниже.


Пример смарт-контракта PayNow


Фрагмент кода ниже представляет собой пример смарт-контракта BookStore, который позволяет людям продавать свои книги в Интернете. Пример включает три функции для обработки платежей по вашему смарт-контракту.


```javascript


// SPDX-идентификатор лицензии: MIT


прочность прагмы >=0,7,0 <0,9,0;


договор Книжный магазин {


// Содержит глобальные данные хранилища


uint256 налоговый сбор;


неизменяемый адрес taxAccount;


uint8 общее предложение = 0;


// Указывает информацию о книге


структура BookStruct {


идентификатор uint8;


адрес продавца;


заголовок строки;


строковое описание;


автор строки;


стоимость uint256;


uint256 метка времени;


// Связываем книги с продавцами и покупателями


BookStruct[] книги;


отображение (адрес => BookStruct []) booksOf;


отображение (uint8 => адрес) общественного продавцаOf;


отображение (uint8 => bool) bookExists;


// Выводит запись о продажах


Событие Распродажа(


идентификатор uint8,


адрес проиндексированного покупателя,


адрес продавца проиндексирован,


стоимость uint256,


uint256 метка времени


// Выход из созданной записи книги


событие Создано(


идентификатор uint8,


адрес продавца проиндексирован,


uint256 метка времени


// Инициализирует налог на продажу книг


конструктор (uint256 _taxFee) {


taxAccount = msg.sender;


налоговый сбор = _налоговый сбор;


// Выполняет создание книги


функция создать книгу(


название строки памяти,


описание строковой памяти,


автор строковой памяти,


стоимость uint256


) public возвращает (bool) {


require(bytes(title).length > 0, "Заголовок пустой");


require(bytes(description).length > 0, "Описание пусто");


require(bytes(author).length > 0, "Описание пусто");


require(cost > 0 ether, "Цена не может быть нулевой");


// Добавляет книгу в магазин


книги.push(


КнигаСтруктура(


общее предложение++,


сообщение.отправитель,


заглавие,


описание,


автор,


Стоимость,


block.timestamp


// Записывает информацию о продаже книг


продавец[общее предложение] = msg.sender;


bookExists[totalSupply] = true;


излучать Создано(


общее предложение,


сообщение.отправитель,


block.timestamp


вернуть истину;


// Выполняет платеж по книге


функция payForBook(идентификатор uint8)


публичная кредиторская задолженность (bool) {


require(bookExists[id], "Книга не существует");


require(msg.value >= books[id - 1].cost, "Слишком мало эфира");


// Вычисляет платежные данные


адрес продавца = продавец[id];


uint256 налог = (msg.value / 100) * taxFee;


uint256 payment = msg.value - налог;


// Покупатель векселей при продаже книг


payTo(продавец, оплата);


payTo(taxAccount, налог);


// Отдаем книгу покупателю


booksOf[msg.sender].push(книги[id - 1]);


выпустить Продажа(


я бы,


сообщение.отправитель,


продавец,


оплата,


block.timestamp


вернуть истину;


// Метод 1: передаточная функция


передача функции(


Отправить,


сумма uint256


) внутренние возвраты (bool) {


подлежащий оплате(кому).перевод(сумма);


вернуть истину;


// Способ 2: Функция отправки


функция отправить(


Отправить,


сумма uint256


) внутренние возвраты (bool) {


требуют(к оплате(к).отправить(сумма), "Платеж не прошел");


вернуть истину;


// Способ 3: функция вызова


функция payTo(


Отправить,


сумма uint256


) внутренние возвраты (bool) {


(логический успех) = подлежащий оплате (кому). call {значение: сумма} ("");


требуют(успех, "Платеж не прошел");


вернуть истину;


// Возвращает книги покупателя


функция myBooks(адрес покупателя)


внешнее представление возвращает (память BookStruct[]) {


вернуть книги[покупатель];


// Возвращает книги в магазине


функция getBooks()


внешнее представление возвращает (память BookStruct[]) {


вернуть книги;


// Возвращает конкретную книгу по id


функция getBook (идентификатор uint8)


внешний вид возвращает (память BookStruct) {


вернуть книги[id - 1];


Шаг за шагом, позвольте мне разобрать это для вас всех, начиная с самого верха…


```javascript


// SPDX-идентификатор лицензии: MIT


прочность прагмы >=0,7,0 <0,9,0;


договор Книжный магазин {


// Здесь идут коды...


Если вы новичок в разработке смарт-контрактов Solidity, вам не о чем беспокоиться. Приведенный выше фрагмент кода представляет собой базовую структуру смарт-контракта.


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


Мы указали диапазон компиляторов Solidity, которые могут успешно скомпилировать наш смарт-контракт. Наконец, мы указали имя контракта BookStore.


```javascript


// Содержит глобальные данные хранилища


uint256 налоговый сбор;


неизменяемый адрес taxAccount;


uint8 общее предложение = 0;


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


```javascript


// Указывает информацию о книге


структура BookStruct {


идентификатор uint8;


адрес продавца;


заголовок строки;


строковое описание;


автор строки;


стоимость uint256;


uint256 метка времени;


За ней следует структура книги, представляющая собой сложную структуру данных для хранения информации о книге. У книги есть идентификатор, продавец, название, описание, автор, цена и временная метка, указывающая, когда книга была добавлена ​​в наш магазин.


```javascript


// Связываем книги с продавцами и покупателями


BookStruct[] книги;


отображение (адрес => BookStruct []) booksOf;


отображение (uint8 => адрес) общественного продавцаOf;


отображение (uint8 => bool) bookExists;


Теперь в приведенном выше коде мы использовали только что созданную структуру книги, чтобы указать массив необходимых данных, которые должны быть собраны в магазине.


Итак, переменная books — это массив книг, а сопоставление booksOf содержит все книги, принадлежащие конкретному покупателю. Отображение продавцаOf возвращает адрес продавца, определенный идентификатором книги. Наконец, сопоставление bookExists возвращает true или false, если в нашем магазине есть книга с указанным идентификатором.


```javascript


// Выводит запись о продажах


Событие Распродажа(


идентификатор uint8,


адрес проиндексированного покупателя,


адрес продавца проиндексирован,


стоимость uint256,


uint256 метка времени


// Выход из созданной записи книги


событие Создано(


идентификатор uint8,


адрес продавца проиндексирован,


uint256 метка времени


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


```javascript


// Инициализирует налог на продажу книг


конструктор (uint256 _taxFee) {


taxAccount = msg.sender;


налоговый сбор = _налоговый сбор;


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


```javascript


// Выполняет создание книги


функция создать книгу(


название строки памяти,


описание строковой памяти,


автор строковой памяти,


стоимость uint256


) public возвращает (bool) {


require(bytes(title).length > 0, "Заголовок пустой");


require(bytes(description).length > 0, "Описание пусто");


require(bytes(author).length > 0, "Описание пусто");


require(cost > 0 ether, "Цена не может быть нулевой");


// Добавляет книгу в магазин


книги.push(


КнигаСтруктура(


общее предложение++,


сообщение.отправитель,


заглавие,


описание,


автор,


Стоимость,


block.timestamp


// Записывает информацию о продаже книг


продавец[общее предложение] = msg.sender;


bookExists[totalSupply] = true;


излучать Создано(


общее предложение,


сообщение.отправитель,


block.timestamp


вернуть истину;


Приведенная выше функция собирает информацию о книге, такую ​​как адрес продавца, название, описание и стоимость книги.


Затем он выполняет проверки, чтобы убедиться, что продавец не предоставляет пустые данные для нашего смарт-контракта. После этого он помещает книгу в массив books, используя нашу ранее определенную структуру book.


Сразу же после добавления книги в магазин сохраняются важные записи для отслеживания тех, кто купил книгу, и продавца этой книги.


Наконец, перед тем, как функция завершается с логическим значением, она выдает или записывает в EVM некоторую важную информацию.


```javascript


// Выполняет платеж по книге


функция payForBook(идентификатор uint8)


публичная кредиторская задолженность (bool) {


require(bookExists[id], "Книга не существует");


require(msg.value >= books[id - 1].cost, "Слишком мало эфира");


// Вычисляет платежные данные


адрес продавца = продавец[id];


uint256 налог = (msg.value / 100) * taxFee;


uint256 payment = msg.value - налог;


// Покупатель векселей при продаже книг


payTo(продавец, оплата);


payTo(taxAccount, налог);


// Отдаем книгу покупателю


booksOf[msg.sender].push(книги[id - 1]);


выпустить Продажа(


я бы,


сообщение.отправитель,


продавец,


оплата,


block.timestamp


вернуть истину;


Теперь это самая важная функция в этом смарт-контракте, потому что это функция, которая приносит вам деньги, когда вы подключаете ее к внешнему интерфейсу.


При вызове функция принимает идентификатор книги, проверяет, существует книга или нет, а также проверяет, достаточно ли вы отправили эфиров для покупки книги.


Затем функция выполняет некоторые расчеты платежа и отправляет проценты платежа сторонам на принимающей стороне.


После завершения платежа книга передается покупателю, и эта информация о продажах регистрируется в EVM.


```javascript


// Возвращает книги покупателя


функция myBooks(адрес покупателя)


внешнее представление возвращает (память BookStruct[]) {


вернуть книги[покупатель];


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


```javascript


// Возвращает книги в магазине


функция getBooks()


внешнее представление возвращает (память BookStruct[]) {


вернуть книги;


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


```javascript


// Возвращает конкретную книгу по id


функция getBook (идентификатор uint8)


внешний вид возвращает (память BookStruct) {


вернуть книги[id - 1];


Наконец, эта функция возвращает книгу из нашего магазина. Вызывающий должен указать идентификатор книги для успешного поиска.


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


3 обязательные функции смарт-контракта


функция TransferTo() с Solidity


// Метод 1: передаточная функция


передача функции(


Отправить,


сумма uint256


) внутренние возвраты (bool) {


подлежащий оплате(кому).перевод(сумма);


вернуть истину;


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


функция sendTo() с Solidity


```javascript


// Способ 2: Функция отправки


функция отправить(


Отправить,


сумма uint256


) внутренние возвраты (bool) {


требуют(к оплате(к).отправить(сумма), "Платеж не прошел");


вернуть истину;


Теперь эта функция добавляет необходимый метод для проверки успешного выполнения платежей. Это так же просто и понятно, как функция TransferTo.


функция payTo() с Solidity


```javascript


// Способ 3: функция вызова


функция payTo(


Отправить,


сумма uint256


) внутренние возвраты (bool) {


(логический успех) = подлежащий оплате (кому). call {значение: сумма} ("");


требуют(успех, "Платеж не прошел");


вернуть истину;


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


TransferTo() против sendTo() против payTo()


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


Функция TransferTo:


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


```javascript


получатель.перевод(сумма);


Два условия приводят к сбою передаточной функции:


  • Если баланс смарт-контракта-отправителя недостаточен, контракт-получатель отклоняет платеж.

  • В случае сбоя передаточная функция восстанавливается.

В случае сбоя передаточная функция восстанавливается. При совершении платежа вызываются функции fallback() или receive() принимающего контракта. Это позволяет получающему контракту ответить на платеж.


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


Функция отправки:


Эта функция использует метод отправки, как показано в коде ниже.


```javascript


получатель.отправить(сумма);


Отправка и передача почти синонимичны в поведении. Однако, если платеж не прошел, он не будет возвращен. Вместо этого он возвращает false. Вызывающий контракт отвечает за обработку сбоев.


Если платеж сделан, вызываются функции fallback() или receive() принимающего контракта. Это позволяет получающему контракту ответить на платеж.


Send также отправляет 2300 галлонов газа контракту-получателю.


Функция оплаты:


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


```javascript


(логический успех,) = Receiver.call {значение: сумма} ("");


Функция call() предназначена для более индивидуального взаимодействия между смарт-контрактами. У него есть возможность вызывать функцию по имени и отправлять ей эфир. Теперь это предпочтительный метод отправки эфира со смарт-контракта.


Вывод


Наконец, мы подошли к завершению этого урока, и, надеюсь, вы получили от него пользу.


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


Спасибо за прочтение, пожалуйста, нажмите кнопку «Нравится», похлопайте в ладоши или сердечко, чтобы показать свою любовь. Увидимся в следующем уроке…


Об авторе


Госпел Дарлингтон начал свой путь в качестве инженера-программиста в 2016 году. За эти годы он приобрел полноценные навыки работы со стеками JavaScript, такими как React, ReactNative, NextJs, а теперь и с блокчейном.


В настоящее время он работает фрилансером, создает приложения для клиентов и пишет технические руководства, обучая других тому, что делает он.


Евангелие в Дарлингтоне открыто и доступно для вас. Вы можете связаться с ним на LinkedIn, Facebook, Github или на его веб-сайте.



Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE