paint-brush
Master Dynamic Data with Solidity Linked Listsby@adamboudj
269 reads

Master Dynamic Data with Solidity Linked Lists

by Adam BoudjemaaNovember 6th, 2023
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Smart contract developers play a vital role in developing innovative applications in the rapidly evolving blockchain landscape. One of the key aspects of this development process is the selection of appropriate data structures that form the foundation of smart contract programming in Solidity. Linked Lists are ideal for storing frequently changing large amounts of data while preserving order.
featured image - Master Dynamic Data with Solidity Linked Lists
Adam Boudjemaa HackerNoon profile picture

Smart contract developers play a vital role in developing innovative applications in the rapidly evolving blockchain landscape.

One of the key aspects of this development process is the selection of appropriate data structures that form the foundation of smart contract programming in Solidity.

Linked Lists provide a dynamic and efficient solution for managing data in smart contracts and show versatility and robustness in tackling blockchain challenges.

Existing Data Structures in Solidity

In Solidity, developers frequently use arrays and mappings. Let’s delve into each:

Arrays:

  • Order Maintenance: Holds the sequence of elements.
  • Indexed Retrieval: Direct element access via an index.
  • Size Fixity (in memory): Pre-defined size requirement in memory.
  • Operation Costliness: Pricy insertions and deletions due to element shifting.

Example: Storing a list of token holders in a DeFi project. For instance, the order could be relevant for distributing rewards based on the order of joining.

Mappings:

  • Swift Access: Rapid data retrieval with unique keys.
  • Boundless Size: Capable of housing endless data.
  • Order Absence: Elements lack a specific sequence.
  • Enumeration Void: Unable to loop through elements or fetch a key list.

Example: Token contract balances can be efficiently managed using a mapping to retrieve address-specific balance information.


These structures are foundational in Solidity yet have limitations, paving the way for exploring other data structures like Linked Lists.

The Downsides of Arrays and Mappings in DeFi

  • Arrays can be expensive for larger lists of liquidity pool stakeholders and may lead to DoS attacks.
  • Mappings struggle with iterating over all stakeholders to update rewards.
  • Linked Lists are a useful data structure that provides flexibility and efficiency, particularly in dynamic environments with inherent limitations.

Linked Lists in Solidity

Linked Lists are ideal for storing frequently changing large amounts of data while preserving order. Unlike arrays, they allow for easy and cost-effective data addition and removal.

Practical Dive: Linked List Implementation in DeFi

This code shows a basic implementation of a LinkedList contract in Solidity. It defines a struct Node and uses mapping nodes to hold the list. It offers CRUD functions to add, update, retrieve, and remove nodes. The head variable keeps track of the start of the list, making it useful for managing data dynamically.


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @title A simple linked list implementation in Solidity
contract LinkedList {
    struct Node {
        uint256 data;
        address next;
    }

    mapping(address => Node) public nodes;
    address public head;

    constructor() {
        head = address(0);
    }

    /// @notice Adds a new node to the list
    /// @param _addr The address to be used as the node identifier
    /// @param _data The data to be stored in the node
    function addNode(address _addr, uint256 _data) public {
        require(nodes[_addr].next == address(0), "Node already exists");
        nodes[_addr] = Node({data: _data, next: head});
        head = _addr;
    }

    /// @notice Retrieves a node's data and the next node's address
    /// @param _addr The address of the node to retrieve
    /// @return The data and the next node's address
    function getNode(address _addr) public view returns (uint256, address) {
        Node memory node = nodes[_addr];
        return (node.data, node.next);
    }

    /// @notice Updates a node's data
    /// @param _addr The address of the node to update
    /// @param _newData The new data to be stored in the node
    function updateNodeData(address _addr, uint256 _newData) public {
        require(nodes[_addr].next != address(0) || head == _addr, "Node does not exist");
        nodes[_addr].data = _newData;
    }

    /// @notice Removes a node from the list
    /// @param _addr The address of the node to remove
    function removeNode(address _addr) public {
        require(nodes[_addr].next != address(0) || head == _addr, "Node does not exist");
        address iterator = head;
        address prev = address(0);
        while (iterator != _addr && iterator != address(0)) {
            prev = iterator;
            iterator = nodes[iterator].next;
        }
        if (prev == address(0)) {
            head = nodes[head].next;  // Removing the head node
        } else {
            nodes[prev].next = nodes[iterator].next;  // Removing a middle or tail node
        }
        delete nodes[_addr];
    }
}

A linked list, like the one in the example contract, can simplify the management of growing data lists. Unlike arrays, it updates easily without rearranging items when lenders join or leave. This ensures straightforward and predictable gas usage, especially in a busy protocol.

Conclusion

Choosing the appropriate data structure is crucial. Although arrays and mappings are helpful, their limitations become evident in some scenarios.

Through exploration of the contract, we have discovered a more effective way to manage data, highlighting the benefits of utilizing linked lists in the development of smart contracts.


Explore More:

Connect with me on: