Here are my contracts:
Mapping design:
pragma solidity >=0.7.0 <0.9.0;
contract Mapping {
struct Entity {
uint data;
address _address;
}
mapping(address => Entity) entities;
// Creates a new entity for msg.sender and adds it to the mapping/array.
function addEntity(uint data) public {
require(entities[msg.sender]._address == address(0), "Entity already exists");
entities[msg.sender] = Entity(data, msg.sender);
}
// Updates the data in a saved entity for msg.sender
function updateEntity(uint data) public {
require(entities[msg.sender]._address != address(0), "Missing entity");
entities[msg.sender] = Entity(data, msg.sender);
}
}
Array design:
pragma solidity >=0.7.0 <0.9.0;
contract Array {
struct Entity {
uint data;
address _address;
}
Entity[] entities;
// Creates a new entity for msg.sender and adds it to the array.
function addEntity(uint data) public {
(bool found, uint idx) = _findIndex(msg.sender);
require(!found, "Entity already exists");
entities.push(Entity(data, msg.sender));
}
// Updates the data in a saved entity for msg.sender
function updateEntity(uint data) public {
(bool found, uint idx) = _findIndex(msg.sender);
require(found, "Missing Entity");
entities[idx] = Entity(data, msg.sender);
}
function _findIndex(address addr) private returns(bool, uint) {
for (uint idx=0; idx<entities.length; idx++) {
if (entities[idx]._address == addr) return (true, idx);
}
return (false, 0);
}
}
Results:
- The Array design consumes more gas because it requires iterating through the array to search for the element to update. Iterating the array is also required for add operation if you want to ensure no duplicate entries in the array exist.
- Updating the last entry in the array is significantly faster in the mapping design and the difference in gas consumption grows linearly with the size of the array.
For example: updating the 5th element of the array requires 32% more gas than updating the 1st but updating the 2nd element only requires 8% more gas than the 1st.