2

I have a struct mapped with an address as the key. I want to iterate through all values of that mapping with another key value, in this case a nonce that I generate in the contract. Is this possible? What is the correct terminology for this process if it is?

I have been pouring over all of Rob Hitchens' storage posts (Are there well-solved and simple storage patterns for Solidity? among others), but I'm stuck conceptually. I know I can just create an array, but since I want to be able to delete records by address, a mapping makes much more sense. I also know I can create a mapping and a second array to track all of the addresses, but that is much more wasteful than having a single mapping.

Here is current code and context:

struct Subscription {
    address subscriberAddress; //Address of the subscriber.
    uint256 timeOfLastCharge; //Time in Unix seconds.
    uint256 nonce;
}

mapping(address => Subscriptions) public subscriptionRegistry; // List of all subscribers. Lookup via subscriber address.

//mapping(address => uint)

function initiateSubscription (address _subscriberAddress) external {

    require(msg.sender == contractManager, "You are not authorized to call this function.");
    require(subscriptionRegistry[_subscriberAddress].subscriberAddress == address(0), "A subscription already exists for this address.");

    Subscription storage newSubscription = Subscriptions[_subscriberAddress];
    newSubscription.subscriberAddress = _subscriberAddress;
    newSubscription.timeOfLastCharge = now;
    newSubscription.nonce = currentNonce;

    tokenContract.transferFrom(_subscriberAddress, merchant, subscriptionPrice);

    emit subscriptionEvent(_subscriberAddress, subscriptionPrice, billingInterval);
}
3
  • a mapping, is a list of key value pair. you can't access the value without the key. You can't iterate on the keys. You need to have the key stored somewhere else to be able to do anything to the its respective value. Commented Aug 2, 2019 at 15:30
  • I know that you can't iterate, but I want to somehow map the same information twice. All strategies I've seen are extremely convoluted. I have a version of Rob Hitchens' strategy (Mapped Structs with Delete-enabled Index) working, but it is very hard to read, and difficult to understand for someone auditing casually. Even with increased gas cost, ease of reading can outweigh everything. In my case, I could just iterate through events to keep track of things, but Infura only goes back the last 1000 or so events, and keeping addresses in a regular database seems like an anti-pattern. Commented Aug 2, 2019 at 19:55
  • 1
    You can map the same struct twice by using a different key, maybe add a random number inside your struct so that with every hash of the struct to create the key you get a new different one. The storing of the keys is in itself an anti pattern of what the mapping is all about. I know that people who use keys in their mapping do it in a way that a wallet address can generate the key that holds the data struct related to that wallet on their smart contract. so basically the user is the one that supplies the key. mappings are basically storage lockers at your bank. Commented Aug 3, 2019 at 9:29

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.