1

Wanted to share what I learned to help someone in the future running into a similar issue:

I have this struct, which includes two arrays. In createNewEvent, I initialize two arrays, confirmedRSVPs and claimedRSVPS, in memory. In createNewRSVP, I add addresses to this array to keep track of people who have RSVP'd.

My question: Should I be using storage since between function calls, memory is reset between calls and is meant to be temp? I don't want to lose track of who has RSVP'd in past executions of newRSVP, the function that adds addresses to that array.

When I changed the arrays to storage, I got this error: This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.

struct CreateEvent {
            bytes32 eventId;
            string eventName; 
            address eventOwner;
            uint256 eventTimestamp;
            uint256 deposit;
            uint256 maxCapacity;
            address[] confirmedRSVPs;
            address[] claimedRSVPs;
            bool paidOut;
        }


mapping(bytes32 => CreateEvent) public idToEvent;

    function createNewEvent(
        uint256 eventTimestamp,
        uint256 deposit,
        uint256 maxCapacity,
        string memory eventName
    ) external {
        // generate an eventID based on other things passed in to generate a hash
        bytes32 eventId = keccak256(
            abi.encodePacked(
                msg.sender,
                address(this),
                eventTimestamp,
                deposit,
                maxCapacity
            )
        );

        address[] memory confirmedRSVPs; 
        address[] memory claimedRSVPs;
        

        //this creates a new CreateEvent struct and adds it to the idToEvent mapping
        idToEvent[eventId] = CreateEvent(
            eventId,
            eventName,
            msg.sender,
            eventTimestamp,
            deposit,
            maxCapacity,
            confirmedRSVPs,
            claimedRSVPs,
            false
        );

    }



function createNewRSVP(bytes32 eventId) external payable {
        // look up event
        CreateEvent storage myEvent = idToEvent[eventId];

        // transfer deposit to our contract / require that they sent in enough ETH
        require(msg.value == myEvent.deposit, "NOT ENOUGH");

        //require that the event hasn't already happened (<eventTimestamp)
        require(block.timestamp <= myEvent.eventTimestamp, "ALREADY HAPPENED");

        //make sure event is under max capacity
        require(
            myEvent.confirmedRSVPs.length < myEvent.maxCapacity,
            "This event has reached capacity"
        );

        //require that msg.sender isn't already in myEvent.confirmedRSVPs
        for (uint8 i = 0; i < myEvent.confirmedRSVPs.length; i++) {
            require(myEvent.confirmedRSVPs[i] != msg.sender, "ALREADY CONFIRMED");
        }

        myEvent.confirmedRSVPs.push(payable(msg.sender)); 

    }

Answer: The elements in the array will persist and be stored because they are defined as part of the struct, which is stored in storage. The way the code is written above is the correct way to do this so that the data saved in your array persists despite the array variable being stored in memory because we are saving it to our struct mapping.

Hope this helps others :-)

1
  • What's the question? What solc version are you testing with?
    – Ismael
    May 11, 2022 at 16:48

0

Your Answer

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

Browse other questions tagged or ask your own question.