I'd like to be able to immediately get a struct value from a mapping after calling a function that updates the struct, however, when testing with Ganache, sometimes the event arrives to the listener before the struct has been updated in the contract. I've noticed that the issue is especially bad when trying to transfer value within the function that emits the event.
Here's a small demo contract to illustrate the issue.
pragma solidity ^0.5.8;
contract Names {
uint lastId;
mapping(uint => Name) public numberedNames;
struct Name {
string name;
}
constructor() public {
lastId = 0;
}
event LogNewName(uint id, string name);
event LogNameUpdate(uint id, string name);
function setName(string memory name) public {
numberedNames[lastId] = Name(name);
emit LogNewName(lastId, name);
lastId++;
}
function changeName(uint id, string memory name, uint transferRequest) public payable {
Name storage existingName = numberedNames[id];
existingName.name = name;
msg.sender.transfer(transferRequest);
emit LogNameUpdate(id, name);
}
}
And here's what I'm trying do in node within the event listener.
async function listenerCallback(data) {
await utils.pause(1000); // pause 1 second - adding this will prevent mappingStruct from being stale, but not an ideal solution
const mappingStruct = await contract.methods.numberedNames(data.returnValues.id);
console.log(mappingStruct)
// update db based on event information
}
Again, if I have a transfer in the function (see the changeName
function above), the value of mappingStruct
will always be stale unless adding a delay. However, even if not transferring value, it is sometimes still stale.
Adding the delay complicates things in my case so it would be highly preferable to address this in the contract code if at all possible.
Any suggestions? Also, since this is my first Ethereum project, will this be an issue on the mainnet?
changeName
?