0

I have a question regarding iterating a mapping with struct array. There is a for loop that iterates over a few thousands times trying to find a matching properties inside the struct.

Ex:

struct MatchBettingInfo {    
    address better;
    uint matchId;
    uint homeScore;
    uint awayScore; 
}

mapping(uint => MatchBettingInfo[]) public matchBettingInfo;  

function claimPrizes(uint _matchId, uint _homeScore, uint _awayScore) public returns (bool) {
    uint totalNumBetters = matchBettingInfo[_matchId].length;  

    // Find matching scores among betters who betted for this match
    for (uint i = 0; i < totalNumBetters; i++) {
        if (matchBettingInfo[_matchId][i].homeScore == _homeScore && 
            matchBettingInfo[_matchId][i].awayScore == _awayScore) {          
            numOfWinners++;
        }  
    }  

    ... more codes
}

This iteration is not inside a view nor constant function. So it takes up some gas while calling it. I'm just worrying the function could be running out of gas if the loop iterates over a huge numbers (over ten thousands?)

Are there any suggestions in terms of optimization?

0

This solution will allow you to avoid loops, which in your application could be catastrophic as the contract could get stuck if there are many users and the gas required for the loop is beyond the limit allowed. I tried to keep it as close as possible to your original implementation:

struct MatchBettingInfo {    
    mapping(bytes32 => address[]) bets;
    mapping(address => uint) homeScore;
    mapping(address => uint) awayScore; 
}

mapping(uint => MatchBettingInfo) public matchBettingInfo;  

Now, setting a bet will be implemented by this function:

function makeBet(uint _matchId, uint _homeScore, uint _awayScore) public {
    bytes32 mybet = keccak256(_homeScore,_awayScore);
    matchBettingInfo[_matchId].bets[mybet].push(msg.sender);
    matchBettingInfo[_matchId].homeScore[msg.sender] = _homeScore;
    matchBettingInfo[_matchId].homeScore[msg.sender] = _awayScore;
}

Now you can get a list of the winners in one shot:

function claimPrizes(uint _matchId, uint _homeScore, uint _awayScore) public returns (bool) {
    bytes32 winnerScore = keccak256(_homeScore,_awayScore);
    uint numOfWinners = matchBettingInfo[_matchId].bets[winnerScore].length;

    // rest of your code

}

How this work?

First, note that the mapping is now a mapping of struct and not a mapping an array of structs.

The winners need to guess both, the home and away score, then this is a unique combination, I save the hash of the two numbers as the bet. The structure also save these numbers for each address in case you require to have them, if you dont, is safe to remove these two mapping called awayScore and homeScore

Now, to get the number of winners is as simple as to get the number of addresses stored in the key that is formed by getting the hash of the homeScore and awayScore.

uint numOfWinners = matchBettingInfo[_matchId].bets[winnerScore].length;

Give you the number of winners and:

matchBettingInfo[_matchId].bets[winnerScore]

will give you the list of winners in one shot!!!

Hope this helps

  • awesome implementation! I have one question tho. Since the struct contains only the indexed types, it is unable to declare state variable matchBettingInfo as public. I need to get length of how many people betted for the matchId – bbusdriver May 30 '18 at 23:05
  • Alright. I just included uint totalNumOfBetters; in the struct and included matchBettingInfo[_matchId].totalNumOfBetters += 1; in the makeBet function. This way I could retrieve the length of how many people betted for the particular matchId. If you have a better idea, please advise. I'll mark this as an answer. Thanks. – bbusdriver May 30 '18 at 23:21
  • I think that will do. – Jaime May 30 '18 at 23:24
0

Why font use a mapping of mapping instead of indexed array? The method you shown consume potentially a Lot of gas, in a non predictable Way.

  • Could you give some examples please. – bbusdriver May 30 '18 at 18:52

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.