Как кодировать смарт-контракт условного депонирования: безопасный подход

Как кодировать смарт-контракт условного депонирования: безопасный подход

23 мая 2022 г.

Вступление


Наш мир постоянно находится под влиянием роста экономики Web3. Это будет иметь большое преимущество для тех, кто в настоящее время извлекает выгоду из этого пространства Web3.


Как показано в * [опросе, проведенном Cointelegraph Research и Keychain Ventures] (https://research-backend.cointelegraph.com/uploads/attachments/cl291bcfe03zdufpdpp3x5vgs-ct-vc-report-2022-q1-report.pdf) * В первом квартале 2022 года в блокчейн-бизнес было инвестировано 14,6 млрд долларов США, что является продолжением тенденции, согласно которой общий объем капитала, вложенного в это пространство, увеличивался каждый квартал с начала 2021 года.


Кроме того, опрос также показал, что средняя стоимость каждой продажи в долларах выросла за последние три месяца и сейчас составляет примерно 32,3 миллиона долларов.


Чтобы разбить отчет, вот что вы должны знать; Пространство Web3 спорадически растет. В этот сектор закачиваются деньги. Эти деньги используются для создания новых систем Web 3.0, которые будут предоставлять услуги людям и приносить доход инвесторам. Но кто те, кто строит эти системы? Они разработчики!


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


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


Если вы так же возбуждены, как и я, давайте приступим к уроку…


Почему вы должны освоить смарт-контракты условного депонирования


![Бесплатная фотография человека, стоящего перед компьютером, с селективным фокусом]


Одним из основных направлений инвестиций в пространство Web 3.0 является разработка децентрализованных финансовых систем (Defi). Эта область экономики Web3 фокусируется на предоставлении платформ для безопасного перемещения денег из одного пункта назначения в другой с молниеносной скоростью. В технологиях Defi есть много комбинаций и различий, но одна из них — это обработка цифровых валют.


Мы живем в мире, где многим людям нельзя доверять денежные обязательства, и поэтому они полагаются на системы условного депонирования.


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


Например, Джеймс, живущий в Алабаме, хочет купить новый MacBook у Дэйва, который продает его из Сан-Франциско. Но Джеймс не знает Дейва, который живет далеко и не может поверить, что он доставит Ноутбук.


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


Поступая таким образом, Джеймс отдает деньги поставщику условного депонирования, а Дэйв также передает поставщику условного депонирования MacBook. Провайдер условного депонирования передает ноутбук Джеймсу и Дэйву деньги за ноутбук, в то время как поставщик условного депонирования получает свою долю.


Вышеупомянутая ситуация - это то, что мы видим в большинстве онлайн-бизнесов, таких как:


  • Покупка и продажа ювелирных изделий.

  • Предприятия по аренде автомобилей.

  • Продажа Автомобили, самолеты, и лодка.

  • Продажа цифровых предметов коллекционирования.

  • Сайты фрилансеров

  • Электронная коммерция и многое другое.

Как работает смарт-контракт условного депонирования


Бесплатная фотография коллег, работающих вместе


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


Покупатель и продавец соглашаются с условиями


Продавец выставляет товар на продажу, а покупатель платит оговоренную цену.


Продавец доставляет товар


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


Покупатель утверждает, и продавец получает деньги


Средства будут автоматически переведены на цифровой кошелек продавца смарт-контрактом.


Пришло время увидеть пример кода солидности для реализации системы условного депонирования.


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


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


Свяжитесь со мной, если вы хотите, чтобы я создал DApp для вашего бизнеса.


```javascript


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


прочность прагмы ^0,8,7;


импортировать "@openzeppelin/contracts/security/ReentrancyGuard.sol";


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


общедоступный адрес escAcc;


uint256 общедоступный escBal;


uint256 общедоступный escAvailBal;


uint256 общедоступный escFee;


uint256 public totalItems = 0;


uint256 общее количество подтвержденных сообщений = 0;


uint256 public totalDisputed = 0;


сопоставление (uint256 => ItemStruct) личных элементов;


сопоставление (адрес => ItemStruct []) private itemsOf;


отображение (адрес => отображение (uint256 => bool)) запрошено публично;


отображение (uint256 => адрес) public ownerOf;


отображение (uint256 => Доступно) public isAvailable;


перечисление Статус {


ОТКРЫТЫМ,


В ОЖИДАНИИ,


ДОСТАВКА,


ПОДТВЕРЖДЕННЫЙ,


СПОРТ,


ВОЗВРАТ,


СНЯТ


перечисление Доступно {НЕТ, ДА}


структура ItemStruct {


uint256 идентификатор элемента;


предназначение строки;


сумма uint256;


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


владелец адреса;


поставщик адресов;


статус статус;


предоставлено логическое значение;


логическое значение подтверждено;


действие события (


uint256 идентификатор элемента,


строка actionType,


статус статус,


адресный индексированный исполнитель


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


escAcc = msg.sender;


escBal = 0;


escAvailBal = 0;


escFee = _escFee;


функция создатьЭлемент(


цель строки calldata


) подлежащие выплате внешние доходы (bool) {


требуют (байты (цель). длина > 0, «Цель не может быть пустой»);


require(msg.value > 0 ether, "Элемент не может быть нулевым эфиром");


uint256 itemId = totalItems++;


Элемент хранилища ItemStruct = items[ItemId];


item.itemId = itemId;


предмет.назначение = цель;


элемент.количество = сообщение.значение;


item.timestamp = блок.timestamp;


элемент.владелец = сообщение.отправитель;


элемент.статус = Статус.ОТКРЫТО;


itemsOf[msg.sender].push(item);


ownerOf[ItemId] = msg.sender;


isAvailable[ItemId] = Доступно.YES;


escBal += msg.value;


испустить действие (


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


"ЭЛЕМЕНТ СОЗДАН",


Статус.ОТКРЫТО,


msg.sender


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


функция getItems()


внешний


Посмотреть


возвращает (реквизит памяти ItemStruct[]) {


реквизит = новый ItemStruct [] (всего элементов);


for (uint256 i = 0; i < totalItems; i++) {


реквизит [я] = предметы [я];


функция getItem (uint256 itemId)


внешний


Посмотреть


возвращает (память ItemStruct) {


вернуть элементы[itemId];


функция моиЭлементы()


внешний


Посмотреть


возвращает (память ItemStruct[]) {


вернуть itemsOf[msg.sender];


функция requestItem (uint256 itemId) возвращает внешний (логический) {


require(msg.sender != ownerOf[itemId], "Владелец не разрешен");


require(isAvailable[itemId] == Available.YES, "Элемент недоступен");


запрашиваемый[msg.sender][itemId] = true;


испустить действие (


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


"ЗАПРОШЕНО",


Статус.ОТКРЫТО,


msg.sender


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


функция одобрить запрос(


uint256 идентификатор элемента,


поставщик адресов


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


require(msg.sender == ownerOf[itemId], "Допускается только владелец");


require(isAvailable[itemId] == Available.YES, "Элемент недоступен");


require(requested[provider][itemId], "Поставщика нет в списке");


isAvailable[itemId] == Available.NO;


элементы[ItemId].статус = Статус.ОЖИДАНИЕ;


элементы [ItemId].provider = поставщик;


испустить действие (


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


"ОДОБРЕННЫЙ",


Статус: ожидание,


msg.sender


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


функция PerformDelievery(uint256 itemId) external возвращает (bool) {


require(msg.sender == items[itemId].provider, "Услуга вам не предоставлена");


require(!items[itemId].provided, "Услуга уже предоставлена");


require(!items[itemId].confirmed, "Услуга уже подтверждена");


элементы[ItemId].provided = true;


элементы[идентификатор элемента].status = Статус.ДОСТАВКА;


испустить действие (


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


"ДОСТАВКА НАЧАЛАСЬ",


Статус.ДОСТАВКА,


msg.sender


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


функция подтверждения доставки(


uint256 идентификатор элемента,


логическое значение предоставлено


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


require(msg.sender == ownerOf[itemId], "Допускается только владелец");


require(items[itemId].provided, "Услуга не предоставлена");


require(items[itemId].status != Status.REFUNDED, "Уже возвращен, создайте новый элемент");


если (при условии) {


плата uint256 = (items[itemId].amount * escFee) / 100;


payTo(items[itemId].provider, (items[itemId].amount - плата));


escBal -= элементы[ItemId].количество;


escAvailBal += комиссия;


элементы[ItemId].confirmed = истина;


элементы[ItemId].status = Статус.ПОДТВЕРЖДЕНО;


всего подтверждено++;


}еще {


items[ItemId].status = Status.DISPUTTED;


испустить действие (


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


"СПОРНЫЙ",


Статус.ОСПОРАНО,


msg.sender


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


функция returnItem(uint256 itemId) внешняя возвращает (bool) {


require(msg.sender == escAcc, "Разрешено только условное депонирование");


require(!items[itemId].confirmed, "Услуга уже предоставлена");


payTo(items[itemId].owner, items[itemId].amount);


escBal -= элементы[ItemId].количество;


элементы[ItemId].статус = Статус.ВОЗВРАТ;


всегоСпорный++;


испустить действие (


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


"ВОЗВРАТ",


Статус.ВОЗВРАТ,


msg.sender


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


функция снятия средств(


Отправить,


сумма uint256


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


require(msg.sender == escAcc, "Разрешено только условное депонирование");


require(количество > 0 эфира && сумма <= escAvailBal, "Нулевой вывод не разрешен");


оплатить(кому, сумма);


escAvailBal -= сумма;


испустить действие (


блок. временная метка,


"СОЗДАНО",


Статус.СОЗДАНО,


msg.sender


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


функция payTo(


Отправить,


сумма uint256


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


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


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


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


Теперь давайте демистифицируем эту функцию смарт-контракта по функциям…


Структурирование смарт-контракта


```javascript


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


прочность прагмы ^0,8,7;


импортировать "@openzeppelin/contracts/security/ReentrancyGuard.sol";


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


// здесь идет код...


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


SPDX означает тип лицензии, которую использует этот смарт-контракт, в то время как прагма говорит об используемой версии компилятора Solidity.


Затем мы импортировали защиту от повторного входа из openzeppelin и унаследовали ее свойства в наших смарт-контрактах.


Затем мы определили имя смарт-контракта как Escrow, связав его с импортированным смарт-контрактом openzeppelin.


Определение переменных смарт-контракта


```javascript


общедоступный адрес escAcc;


uint256 общедоступный escBal;


uint256 общедоступный escAvailBal;


uint256 общедоступный escFee;


uint256 public totalItems = 0;


uint256 общее количество подтвержденных сообщений = 0;


uint256 public totalDisputed = 0;


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


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


Плата за условное депонирование будет иметь оговоренную процентную комиссию за каждую транзакцию. Это будет введено в момент развертывания смарт-контракта.


У нас также есть три переменные, отслеживающие общее количество созданных, подтвержденных или оспариваемых элементов на этой платформе.


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


```javascript


сопоставление (uint256 => ItemStruct) личных элементов;


сопоставление (адрес => ItemStruct []) private itemsOf;


отображение (адрес => отображение (uint256 => bool)) запрошено публично;


отображение (uint256 => адрес) public ownerOf;


отображение (uint256 => Доступно) public isAvailable;


Карта Items() будет отслеживать все предметы, созданные на этом рынке, она использует определенную структуру предметов, которую вы можете увидеть в следующем блоке.


ItemsOf() содержит элементы определенного пользователя в соответствии с его адресом. Requested() отслеживает каждый предмет, запрошенный пользователем, всякий раз, когда предмет становится доступным на рынке.


OwnerOf() отслеживает владельца или создателя каждого элемента, а isAvailable() отслеживает элементы, которые не были назначены другому лицу для доставки.


Определение структур и перечислений


```javascript


перечисление Статус {


ОТКРЫТЫМ,


В ОЖИДАНИИ,


ДОСТАВКА,


ПОДТВЕРЖДЕННЫЙ,


СПОРТ,


ВОЗВРАТ,


СНЯТ


перечисление Доступно {НЕТ, ДА}


структура ItemStruct {


uint256 идентификатор элемента;


предназначение строки;


сумма uint256;


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


владелец адреса;


поставщик адресов;


статус статус;


предоставлено логическое значение;


логическое значение подтверждено;


Перечисление Status определяет различные статусы, которые будет проходить элемент до и после разрешения споров. Перечисления представляют символы как целые числа, начиная с нуля и заканчивая бесконечностью. Но разумно делать структуры enum короткими ради удобства сопровождения.


Доступно другое перечисление, указывающее, был ли элемент назначен человеку или нет. И ItemStruct() — это структура, определяющая детали каждого элемента.


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


Указание события и конструктора


```javascript


действие события (


uint256 идентификатор элемента,


строка actionType,


статус статус,


адресный индексированный исполнитель


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


escAcc = msg.sender;


escBal = 0;


escAvailBal = 0;


escFee = _escFee;


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


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


Функция СоздатьЭлемент()


```javascript


функция создатьЭлемент(


цель строки calldata


) подлежащие выплате внешние доходы (bool) {


// Проверка параметров


требуют (байты (цель). длина > 0, «Цель не может быть пустой»);


require(msg.value > 0 ether, "Элемент не может быть нулевым эфиром");


// Создание элемента


uint256 itemId = totalItems++;


Элемент хранилища ItemStruct = items[ItemId];


item.itemId = itemId;


предмет.назначение = цель;


элемент.количество = сообщение.значение;


item.timestamp = блок.timestamp;


элемент.владелец = сообщение.отправитель;


элемент.статус = Статус.ОТКРЫТО;


// Назначение владельцу и указание доступности


itemsOf[msg.sender].push(item);


ownerOf[ItemId] = msg.sender;


isAvailable[ItemId] = Доступно.YES;


escBal += msg.value;


// Выдача или регистрация информации о созданном элементе


испустить действие (


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


"ЭЛЕМЕНТ СОЗДАН",


Статус.ОТКРЫТО,


msg.sender


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


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


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


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


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


Функция GetItems()


```javascript


функция getItems()


внешний


Посмотреть


возвращает (реквизит памяти ItemStruct[]) {


реквизит = новый ItemStruct [] (всего элементов);


for (uint256 i = 0; i < totalItems; i++) {


реквизит [я] = предметы [я];


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


Функция ПолучитьЭлемент()


```javascript


функция getItem (uint256 itemId)


внешний


Посмотреть


возвращает (память ItemStruct) {


вернуть элементы[itemId];


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


Функция МоиЭлементы()


```javascript


функция моиЭлементы()


внешний


Посмотреть


возвращает (память ItemStruct[]) {


вернуть itemsOf[msg.sender];


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


Функция RequestItem()


```javascript


функция requestItem (uint256 itemId)


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


// Выполняет необходимую проверку записи


require(msg.sender != ownerOf[itemId], "Владелец не разрешен");


require(isAvailable[itemId] == Available.YES, "Элемент недоступен");


// Помещает запрос на элемент


запрашиваемый[msg.sender][itemId] = true;


испустить действие (


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


"ЗАПРОШЕНО",


Статус.ОТКРЫТО,


msg.sender


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


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


Функция ApproveRequest()


```javascript


функция одобрить запрос(


uint256 идентификатор элемента,


поставщик адресов


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


// Проверяет существенное требование


require(msg.sender == ownerOf[itemId], "Допускается только владелец");


require(isAvailable[itemId] == Available.YES, "Элемент недоступен");


require(requested[provider][itemId], "Поставщика нет в списке");


// Назначает элемент поставщику


isAvailable[itemId] == Available.NO;


элементы[ItemId].статус = Статус.ОЖИДАНИЕ;


элементы [ItemId].provider = поставщик;


испустить действие (


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


"ОДОБРЕННЫЙ",


Статус: ожидание,


msg.sender


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


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


Функция выполнения доставки()


```javascript


функция выполнения доставки (uint256 itemId)


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


// Проверяет наличие существенных условий


require(msg.sender == items[itemId].provider, "Услуга вам не предоставлена");


require(!items[itemId].provided, "Услуга уже предоставлена");


require(!items[itemId].confirmed, "Услуга уже подтверждена");


// Помечает элемент как предоставленный


элементы[ItemId].provided = true;


элементы[идентификатор элемента].status = Статус.ДОСТАВКА;


испустить действие (


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


"ДОСТАВКА НАЧАЛАСЬ",


Статус.ДОСТАВКА,


msg.sender


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


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


Функция подтверждения доставки()


```javascript


функция подтверждения доставки(


uint256 идентификатор элемента,


логическое значение предоставлено


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


// Проверяет жизненное состояние


require(msg.sender == ownerOf[itemId], "Допускается только владелец");


require(items[itemId].provided, "Услуга не предоставлена");


require(items[itemId].status != Status.REFUNDED, "Уже возвращен, создайте новый элемент");


// Указывает статус доставки


если (при условии) {


// Платит провайдеру


плата uint256 = (items[itemId].amount * escFee) / 100;


payTo(items[itemId].provider, (items[itemId].amount - плата));


// Повторно калибрует записи


escBal -= элементы[ItemId].количество;


escAvailBal += комиссия;


элементы[ItemId].confirmed = истина;


// Помечает как подтвержденное


элементы[ItemId].status = Статус.ПОДТВЕРЖДЕНО;


всего подтверждено++;


}еще {


// Отмечает как оспариваемый


items[ItemId].status = Status.DISPUTTED;


испустить действие (


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


"СПОРНЫЙ",


Статус.ОСПОРАНО,


msg.sender


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


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


Функция RefundItem()


```javascript


функция returnItem (uint256 itemId)


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


// Проверяет существенное условие


require(msg.sender == escAcc, "Разрешено только условное депонирование");


require(!items[itemId].confirmed, "Услуга уже предоставлена");


// выполняет возврат и перекалибровку записи


payTo(items[itemId].owner, items[itemId].amount);


escBal -= элементы[ItemId].количество;


элементы[ItemId].статус = Статус.ВОЗВРАТ;


всегоСпорный++;


испустить действие (


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


"ВОЗВРАТ",


Статус.ВОЗВРАТ,


msg.sender


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


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


Функция WithdrawFund()


```javascript


функция снятия средств(


Отправить,


сумма uint256


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


// Проверяет существенное условие


require(msg.sender == escAcc, "Разрешено только условное депонирование");


require(количество > 0 эфира && сумма <= escAvailBal, "Нулевой вывод не разрешен");


// Отправляет деньги на адрес


оплатить(кому, сумма);


escAvailBal -= сумма;


испустить действие (


блок. временная метка,


"СОЗДАНО",


Статус.СОЗДАНО,


msg.sender


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


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


Функция PayTo()


```javascript


функция payTo(


Отправить,


сумма uint256


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


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


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


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


Наконец, эта функция безопасно отправляет указанную сумму денег со смарт-контракта на другой счет.


Вот как вы создаете смарт-контракт условного депонирования…


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


Вывод


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


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


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


Кроме того, ознакомьтесь с моими предыдущими уроками, подпишитесь, следуйте за мной и ставьте палец вверх.


Я снова увижу вас в следующем уроке…


Об авторе


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


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


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



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