0

I have a contract which maintains a map of valid wallets.

In this map, the keys are wallet addresses and the values are wallet parameters:

struct WalletParams {
    bool valid;
    uint x;
    uint y;
    uint z;
}

mapping(address => WalletParams) public map;

In order to keep track of valid wallets, I can do either one of the following every time I add a wallet:

  1. Emit an event with the wallet address
  2. Add the wallet address to an auxiliary array

Initially, I thought I should do both, in order to achieve the following goals:

  1. Events can be used in order to perform specific queries and filter out specific wallets
  2. The array can be used in order to be able to fetch all the wallets at any given moment

With regards to #2, I'm starting to think that perhaps events are sufficient for this purpose. In "traditional systems", an array would be the simplest way of course. But on the block-chain, I've figured, maybe the array is "scattered" across different blocks just like the events would be, so there shouldn't be any advantage in maintaining this array.

Is that correct?

If yes, then I should obviously get rid of the array, because of the natural downsides:

  • Additional gas cost
  • Additional code-complexity (which increases the chances for bugs)

Then I realized yet another advantage in an array:

I can easily retrieve the data via any standard wallet application, like MyEtherWallet, which would not be feasible via events.

So in short, is it a custom method to keep an auxiliary array of keys next to a map, or should I get rid of it and rely solely on events?

Here is my contract:

pragma solidity 0.4.24;

import "openzeppelin-solidity/contracts/ownership/Ownable.sol";

contract MyContract is Ownable {
    address[] public array;

    struct WalletParams {
        bool valid;
        uint x;
        uint y;
        uint z;
    }

    mapping(address => WalletParams) public map;

    event WalletUpdated(address indexed wallet);
    event WalletInserted(address indexed wallet);

    function insert_or_update(address wallet, uint x, uint y, uint z) external onlyOwner {
        WalletParams storage walletParams = map[wallet];
        if (walletParams.valid) {
            walletParams.x = x;
            walletParams.y = y;
            walletParams.z = z;
            emit WalletUpdated(wallet);
        }
        else {
            walletParams.valid = true;
            walletParams.x = x;
            walletParams.y = y;
            walletParams.z = z;
            array.push(wallet);
            emit WalletInserted(wallet);
        }
    }

    function getArray() external view returns (address[]) {
        return array;
    }

    function getCount() external view returns (uint) {
        return array.length;
    }
}

Thank you!

1

I guess the question is whether or not you need to be able to get the list of keys from within the contract. I wouldn't worry about sites like MyEtherWallet or MyCrypto being able to fetch the keys, as I don't think that would be that useful when you could just have a dapp that looks through the events to find the list.

There are definitely circumstances where it is necessary/useful to have the list, like perhaps when the list will always be small and the mapping needs to be iterable, but if the list grows unbounded, then I would say forget the array.

  • 1
    you mean forget the array, right? – Jaime Nov 2 '18 at 11:27
  • Yeah, my bad! Corrected – flygoing Nov 2 '18 at 11:55
  • Thank you. The size of the list is actually unbounded (or at least, we expect this list to be very large). In addition, we don't have the need to iterate the list from the on-chain (i.e., from another contract), only from the off-chain.But I fail to understand the bottom line of your answer in light of your opening statement. I actually do need to get the list of keys (from the off-chain), so why should I get rid of the array? Thank you! – goodvibration Nov 2 '18 at 12:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.