Probably Nothing
So basically, I hope to teach and learn in the process, since I tend to forget a lot. I will start by teaching some topics I have studied in Solidity. Today's topic will be on arrays.
How to Write an Array in Solidity and Everything You Need to Know About Arrays
What an array is
How to initialize an array
How to use an array in a function
How to use push, get, update, delete, and pop in an array
An array is a data structure used to store a collection of data. In case you don't know what a data structure is, it is a format for storing, organizing, processing, and retrieving data. Let's get into it.
Arrays can be either dynamic or fixed. A fixed-size array means that the array has a set size. If you try to add more data than the array can hold, you will get an error. An example of a fixed uint array is:
uint[5] public age; // This shows a uint datatype array with a fixed size of 5, meaning the array can hold only 5 elements. It is public and named 'age'.
A dynamic array means the size of the array can change. For example:
uint[] public age; // This allows us to add as many elements as we want.
To initialize an array, we specify the data using an equal sign and square brackets. For example:
uint[] public dynamicArray = [1, 2, 3, 4, 5, 6];
uint[3] public fixedArray = [1, 2, 3];
Let's say we write a smart contract that specifies an array and decide to push new data to the array. For example:
function examples() public {
age.push(7); // This adds 7 to the dynamic array, making it [1, 2, 3, 4, 5, 6, 7]
uint x = age[3]; // This gets the data at index 3, which is 4
age[3] = 8; // This updates the data at index 3 to 8
delete age[3]; // This deletes the data at index 3
}
age[5] //it becomes [1,2,3,4,5,0]
age.pop()
// This deletes the last element of the array- To get the length, we write
age.length
- To get the length, we write
To create an array in memory, it has to have a fixed size.
uint[] memory age = new uint[](9);
Notes on Enum Types
Enum Types: A Tool for Cleaner Code
Enum types provide a structured way to define a set of related constants. This can make your code more readable, maintainable, and less prone to errors.
Consider this example:
Solidity
if (player.movement == 2) {
// player is moving up
} else if (player.movement == 1) {
// player is moving to the left
}
While the comments are helpful, they're not foolproof. If the movement
values were changed, the code would break. Additionally, without the comments, it would be difficult to understand which direction corresponds to each number.
An enum can solve these problems:
Solidity
enum Directions {
Up,
Left,
Down,
Right
}
if (player.movement == Directions.down) {
// ...
} else if (player.movement == Directions.up) {
// ...
}
By using an enum, we replace the numbers with clear, descriptive names. This makes the code more readable and easier to understand. Furthermore, the Directions
enum provides a central definition for all possible directions, ensuring consistency across different parts of your code. If the underlying values change, the rest of your code will remain unaffected as long as you use the enum consistently.
Quick one, Storage variables can be called state variables.
Creating a multisig wallet:
// SPDX-License-Identifier: UNLICENSED
This line specifies the license for the contract.
pragma solidity ^0.8.24;
This declares the Solidity version to be used.
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
Imports the ERC20 interface from OpenZeppelin.
contract Multisig {
Declares the Multisig contract.
uint8 public quorum;
uint8 public noOfValidSigners;
uint256 public txCount;
uint8 public pendingQuorum;
Declares state variables for quorum, number of valid signers, transaction count, and pending quorum.
struct Transaction {
uint256 id;
uint256 amount;
address sender;
address recipient;
bool isCompleted;
uint256 timestamp;
uint256 noOfApproval;
address tokenAddress;
address[] transactionSigners;
}
Defines a struct to store transaction details.
mapping(address => bool) public isValidSigner;
mapping(uint => Transaction) transactions;
mapping(address => mapping(uint256 => bool)) public hasSigned;
Declares mappings to track valid signers, transactions, and signatures.
constructor(uint8 _quorum, address[] memory _validSigners) {
// ... (constructor logic)
}
Constructor to initialize the contract with quorum and valid signers.
event TransferInitiated(uint count, uint id);
event ApprovalSuccessful();
event QuorumUpdateInitiated();
event QuorumUpdateSuccessful();
Declares events for various contract actions.
function transfer(uint256 _amount, address _recipient, address _tokenAddress) external {
// ... (transfer logic)
}
Function to initiate a transfer transaction.
function approveTx(uint8 _txId) external {
// ... (transaction approval logic)
}
Function for signers to approve a transaction.
function updateQuorum(uint8 _newquorum) external {
// ... (quorum update initiation logic)
}
Function to initiate a quorum update.
function approveQuorumUpdate(uint8 _txId) external {
// ... (quorum update approval logic)
}
Function for signers to approve a quorum update.
function getCount() external view returns (uint count) {
count = txCount;
}
View function to get the total transaction count.
function getTx(uint _txId) external view returns (Transaction memory) {
return transactions[_txId];
}
View function to retrieve details of a specific transaction.
This contract implements a multi-signature wallet for ERC20 tokens, allowing multiple signers to approve transactions and governance changes.
after creating the multisig wallet i, i ran a unit test and deployed on the Lisk ecosystem.
Subscribe to my newsletter
Read articles from Chukwuma Miracle directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by