Mapeamento Iterável

porMatheusem02/06/2022

Nesse artigo iremos aprender a criar uma aplicação utilizando o mapeamento iterável através da criação de um contrato inteligente.

Iterando um mapping

Na blockchain, você não pode iterar através de um mapping. Então aqui está um exemplo de aplicação de como criar um mapping iterável.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
library IterableMapping {
// mapping iterável através de address para uint;
struct Map {
address[] keys;
mapping(address => uint) values;
mapping(address => uint) indexOf;
mapping(address => bool) inserted;
}
// Retorna o valor do map utilizando a key como parâmetro
function get(Map storage map, address key) public view returns (uint) {
return map.values[key];
}
// Retorna a key definida no index passado por parâmetro
function getKeyAtIndex(Map storage map, uint index) public view returns (address) {
return map.keys[index];
}
// Retorna o tamanho de keys existentes no mapa
function size(Map storage map) public view returns (uint) {
return map.keys.length;
}
// Grava no mapa passado por parâmetro o endereço da key e valor a ser salvo
function set(
Map storage map,
address key,
uint val
) public {
if (map.inserted[key]) {
map.values[key] = val;
} else {
map.inserted[key] = true;
map.values[key] = val;
map.indexOf[key] = map.keys.length;
map.keys.push(key);
}
}
// Remove do mapa passado por parâmetro o valor do endereço
// se existente no mapa
function remove(Map storage map, address key) public {
if (!map.inserted[key]) {
return;
}
delete map.inserted[key];
delete map.values[key];
uint index = map.indexOf[key];
uint lastIndex = map.keys.length - 1;
address lastKey = map.keys[lastIndex];
map.indexOf[lastKey] = index;
delete map.indexOf[key];
map.keys[index] = lastKey;
map.keys.pop();
}
}
contract TestIterableMap {
using IterableMapping for IterableMapping.Map;
IterableMapping.Map private map;
function testIterableMap() public {
map.set(address(0), 0);
map.set(address(1), 100);
map.set(address(2), 200); // insert
map.set(address(2), 200); // update
map.set(address(3), 300);
for (uint i = 0; i < map.size(); i++) {
address key = map.getKeyAtIndex(i);
assert(map.get(key) == i * 100);
}
map.remove(address(1));
// keys = [address(0), address(3), address(2)]
assert(map.size() == 3);
assert(map.getKeyAtIndex(0) == address(0));
assert(map.getKeyAtIndex(1) == address(3));
assert(map.getKeyAtIndex(2) == address(2));
}
}

Testar no Remix