But if a value is stored in an event, is there an efficient way to retrieve its value from a web3.js script (which is not running all the time and so cannot effectively subscribe to events)?
There is a stateless (almost) pattern to consider.
pragma solidity 0.5.16;
contract BreadCrumbs {
uint public prevChange;
event LogChange(string arg1, string arg2, string arg3. uint previous);
function change(string memory _arg1, string memory _arg2, string memory _arg3) public {
emit LogChange(_arg1, _arg2, _arg3, prevChange);
prevChange = block.number;
}
}
The general idea is to stuff information into logs which are several orders of magnitude cheaper than contract state variables.
prevChange()
give a block number where the latest values are so that greatly reduces the amount of fishing through logs a client would otherwise be required to do. IN many cases, the latest value is the only value of interest.
If it's 0
then there is no information.
History can be explored in reverse order by following the hints until 0
.
Another popular pattern to write the heavy data somewhere else, e.g. IPFS, and then write the url so clients can find it, and the hash so clients can know it's authentic. IPFS addresses both concerns in one move. The information you need will pack into a bytes32
that you can either store or log.
If I indeed decide to store in a contract, should I make a second contract specifically for name storages? (because storing names in the main contract storage would break single responsibility principle and abstraction pattern)
You may have read about the Eternal Storage pattern for upgradable contracts. I think the way you decide to separate concerns varies with a number of considerations. It would not be unusual to create a compact, not-upgradeable contract that encapsulates the state and the logic. That's what the majority do if I'm not mistaken.
Hope it helps.