Как дедуплицировать массивы в Solidity
Как дедуплицировать массивы в Solidity

1. Введение

Solidity — это язык программирования смарт-контрактов для платформы Ethereum с синтаксической структурой, аналогичной JavaScript и C++. Он специально разработан для написания самоисполняющихся контрактов на блокчейне, поддержки разработки сложной бизнес-логики и децентрализованных приложений (dApps). С быстрым развитием технологии блокчейна Solidity стал предпочтительным языком для построения децентрализованных финансов (DeFi), рынков NFT и других приложений блокчейна (на самом деле, это в основном связано с большим количеством пользователей Ethereum).

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

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

2. Основы работы с массивами в Solidity

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

2.1 Базовое использование массивов в Solidity

существовать Solidity , метод определения и использования массивов очень интуитивно понятен. Типы массивов состоят из типа элемента и квадратных скобок, например. uint256[] Экспресс одининдивидуальныйдинамический массив,uint256[5] представляет собой содержащий 5 индивидуальный uint256 Статический массив элементов.

Вот несколько основных примеров манипуляций с массивами:

Язык кода:javascript
копировать
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ArrayExample {
    // динамический массив
    uint256[] public dynamicArray;

    // статический массив
    uint256[5] public staticArray;

    // Добавьте элементы в мотивацию массив
    function addElement(uint256 element) public {
        dynamicArray.push(element);
    }

    // Исправлятьстатический массиввэлемент    function setElement(uint256 index, uint256 element) public {
        require(index < staticArray.length, "Index out of bounds");
        staticArray[index] = element;
    }

    // получатьдинамический массивиз длины
    function getDynamicArrayLength() public view returns (uint256) {
        return dynamicArray.length;
    }
}

2.2 Разница между динамическими и статическими массивами

статический массив:статический массивиз длинысуществовать Определяется во время компиляции,исуществовать Не может быть изменено в течение жизненного цикла контракта.。использоватьстатический Использование массивов в качестве преимуществ заключается в том, что затраты на их эксплуатацию из хранилищ относительно невелики, поскольку они не требуют динамического изменение размера。статический Массив часто используется в контрактах, которым необходимо обрабатывать фиксированное количество транзакций, например фиксированное количество участников или предопределенное постоянное значение.

Язык кода:javascript
копировать
// Определение 1 «Индивидуальное лицо» содержит 3 индивидуальныйэлементизстатический массив
uint256[3] public staticArray = [1, 2, 3];

динамический массив:динамический массивиз длинасуществовать контракта является переменной в течение его жизненного цикла,Разработчики могутиспользовать push Метод добавляет элементы в массив. Хотя динамические массивы обеспечивают гибкость, они также обладают более высокими gas расходы, особенно когда существование добавляет и удаляет элементы. динамичный Массив подходит для сценариев, в которых необходимо обрабатывать переменное количество данных, таких как списки адресов пользователей или записи транзакций.

Язык кода:javascript
копировать
// Определение 1индивидуальныйдинамический массив
uint256[] public dynamicArray;

// Кдинамический Добавляем элементы в массив
dynamicArray.push(4);

2.3 Стоимость газа при операциях с массивами и ее важность в смарт-контрактах

существовать смарт-контракт,Каждая множество операций будет потреблять определенное количество газа., поскольку операция включает в себя чтение и запись в виртуальную машину Ethereum (EVM). Газ, особенно в сети Ethereum Стоимость напрямую влияет на комиссию за транзакцию, поэтому эффективность операций с массивом особенно важна.

  • Операция чтения:существоватьмножество Читать вданныеиз gas Расходы относительно невелики и обычно требуют только доступа к устройству хранения.
  • операция записи:операция записииз gas расходы выше, поскольку они включают в себя запись данных в Ethereum из хранилища персистентности.
  • Динамическое изменение размера:длядинамический массив, каждый раз push Эта операция не только требует написания новых элементов, но также может включать в себя множество операций изменения размера, которые добавят дополнительные элементы. gas расходы。

Оптимизированные операции с массивами Solidity Разработайте индивидуальные ключевые моменты. Чтобы уменьшить ненужное gas Потребление: разработчики обычно тщательно учитывают множество методов использования и работы в логике контракта. Например, старайтесь избегать многократного выполнения цикла существования операции. записи или существование. Используйте медленную, когда в этом нет необходимости. массив。

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

3. Проблемы дедупликации в Solidity

существуют смарт-контракты в разработке, Solidity Ограничения часто влияют на то, как разработчики реализуют определенные функции. Одним из существенных ограничений является то, что Solidity Не поддерживается напрямую, как JavaScript в Set Такая из динамической структуры данных. Это делает существование Solidity Обработка операций сбора данных (например, дедупликации) становится более сложной и дорогостоящей.

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

3.1 Ограничения твердости

  1. Не хватает структур данных высокого уровня.:Solidity В настоящее время поддерживаются только базовые изданные структуры, такие как множество картографий. Хотя этих структур данных достаточно для удовлетворения многих простых потребностей, их недостаточно при выполнении более сложных изданных операций, таких как автоматическая дедупликация или сортировка. и JavaScript Разные, Солидность Нет родного из Set type, что означает, что нет прямого способа хранения уникальных значений.
  2. Затраты на эксплуатацию хранилища высоки:Solidity Любая операция записи, особенно если речь идет о постоянной памяти (хранилище), потребляет много ресурсов. газ. Чем больше хранилищеизданных, тем сложнее эксплуатация и потребление gas тем выше. Таким образом, построение сложной структуры или выполнение нескольких операций записи значительно ускорят развертывание и выполнение контракта.
  3. Нет родного из Установить операции:Solidity Отсутствие встроенной поддержки операций сбора данных. как существовать JavaScript используется в Set из add метод автоматического удаления дубликатов или используйте has Способы быстрого поиска элементов с такими существующими Solidity Все нужно реализовывать вручную. в целом,Это требует написания дополнительной логики и циклов.,Дальнейшее увеличение сложности контракта и затрат на его исполнение.

3.2 Сложность реализации дедупликации в Solidity

существовать Solidity Основная сложность дедупликации заключается в том, как обеспечить одновременно уникальность и контроль. gas расходы. Вот некоторые проблемы при реализации дедупликации:

  1. Высокий и высокий gas расходы:Чтобы добиться дедупликации,Разработчикам необходимо пройти через все элементы множества,И обычно необходимо проверить, сохранился ли каждый отдельный элемент в процессе обхода. Использование сопоставлений или наборов для отслеживания просмотренных элементов является распространенным решением.,Но каждый визити Исправлять Картирование будет потреблять Газ, особенно когда его количество велико, может быть очень высоким.
  2. хранилище Пространство из отходов:Для достижения дедупликации,Нам нужны дополнительные изданные структуры, чтобы отслеживать, какие из элементов были обработаны. Например,Используйте сопоставление, чтобы записать, произошел ли индивидуальный элемент,Хотя таким образом можно сделать операцию поиска из Временной классификации равной O(1), но само отображение требует дополнительного места, что увеличивает общий контракт хранилищарасходов. Что еще хуже, хранилищесуществовать постоянно хранится в блокчейне, а это означает, что такое дополнительное потребление будет долгосрочным.
  3. Ограничение по пределу газа:Сопряжение с сетью Ethereumиндивидуальныйисполнение сделкииз gas Существует верхний предел количества (т. gas лимит). Если контрактная функция существует, потребляет при выполнении gas Если этот лимит превышен, транзакция будет отменена, и контракт не будет успешно выполнен. Сложность операций дедупликации может привести к gas Потребление быстро увеличивается, особенно когда приходится иметь дело с многочисленными операциями дедупликации, вложенными в большое количество или существующую сложную логику.

4. Способ 1. Используйте коллекции (или сопоставления) для удаления дубликатов.

Ниже приведен индивидуальный вариант использования openzepplin из EnumerableSet KuLai быстро дедуплицирует адрес раздачи из примера смарт-контракта:

Язык кода:javascript
копировать
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// version >= v3.3.0
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

contract AirdropUniqueAddresses {
    // Using the EnumerableSet library for AddressSet
    using EnumerableSet for EnumerableSet.AddressSet;

    // Declare a state variable of type EnumerableSet.AddressSet to store unique addresses
    EnumerableSet.AddressSet private seen;

    // Function to add an address to the set if it is not already present
    function addAirdropAddress(address _address) public returns (bool) {
        // Add the address to the set
        // Returns true if the address was not already in the set, false otherwise
        return seen.add(_address);
    }

    // Function to check if an address is already in the set
    function isAirdropAddressSeen(address _address) public view returns (bool) {
        // Check if the address is in the set
        return seen.contains(_address);
    }

    // Function to get the total number of unique addresses in the set
    function getTotalUniqueAddresses() public view returns (uint256) {
        // Return the number of unique addresses in the set
        return seen.length();
    }

    // Function to retrieve an address by index in the set
    function getAirdropAddressAtIndex(uint256 index) public view returns (address) {
        // Ensure the index is within the bounds of the set
        require(index < seen.length(), "Index out of bounds");
        // Retrieve the address at the specified index
        return seen.at(index);
    }

    // Function to remove an address from the set
    function removeAirdropAddress(address _address) public returns (bool) {
        // Remove the address from the set
        // Returns true if the address was in the set and removed, false otherwise
        return seen.remove(_address);
    }
}
  • преимущество
    • Эффективность: картирование существующих Solidity предоставлено в O(1) из Найти время.
    • Легко реализовать: логика проста и понятна.
  • недостаток
    • Требуются дополнительные помещения, может увеличиться gas расходы。
    • Невозможно создать сопоставление динамически,Необходимо определиться заранееданныеструктура:Код такойсуществовать Во время компиляции будет сообщено об ошибкеUninitialized mapping. Mappings cannot be created dynamically, you have to assign them from a state variable.
Язык кода:javascript
копировать
mapping(uint256 => bool) memory seen;
uint256[] memory input = [1, 2, 2, 3, 4, 4];
for (uint256 i = 0; i < input.length; i++) {
    if (!seen[input[i]]) {
        seen[input[i]] = true;
    }
}

5. Способ 2: Дедупликация двойного цикла

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

Язык кода:javascript
копировать
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract AirdropUniqueAddresses {
    // Function to get the unique addresses after removing duplicates
    function getUniqueAirdropAddresses(address[] airdropAddresses;) public view returns (address[] memory) {
        // Calculate the length of the airdropAddresses array
        uint256 length = airdropAddresses.length;

        // Create a dynamic array to store unique addresses
        address[] memory uniqueAddresses = new address[](length);
        uint256 uniqueCount = 0;

        // Outer loop to iterate through each address in the airdropAddresses array
        for (uint256 i = 0; i < length; i++) {
            bool isDuplicate = false;

            // Inner loop to check if the address is already in the uniqueAddresses array
            for (uint256 j = 0; j < uniqueCount; j++) {
                if (airdropAddresses[i] == uniqueAddresses[j]) {
                    isDuplicate = true;
                    break;
                }
            }

            // If the address is not a duplicate, add it to the uniqueAddresses array
            if (!isDuplicate) {
                uniqueAddresses[uniqueCount] = airdropAddresses[i];
                uniqueCount++;
            }
        }

        // Create a new array with the size of uniqueCount to store the final unique addresses
        address[] memory finalUniqueAddresses = new address[](uniqueCount);

        // Copy the unique addresses to the final array
        for (uint256 k = 0; k < uniqueCount; k++) {
            finalUniqueAddresses[k] = uniqueAddresses[k];
        }

        return finalUniqueAddresses;
    }
}
  • преимущество
    • Никаких дополнительных изхранилищ не требуется.,Очень экономит место.
    • Подходит для небольших объемов данных,Просто и легко понять.
  • недостаток
    • Временная сложность равна O(n^2),длябольшойданные Набор не применим。
    • может вызвать высокий gas Потребление, не рекомендуется для производственных сред используется в。

6. Справочные материалы

  1. https://docs.soliditylang.org/zh/v0.8.21/types.html
  2. https://docs.openzeppelin.com/contracts/3.x/api/utils#EnumerableSet
  3. https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/structs/EnumerableSet.sol
boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose