0

I want to add elements in moneyLineData of a Bet instance.

pragma solidity ^0.5.0;
pragma experimental ABIEncoderV2;

contract Betting {

    struct Bet{
        uint betId;
        string question;
        mapping(uint => MoneyLineData) moneyLineData;
        uint lengthMoneyLineData;
    }

    struct MoneyLineData{
        string option;
        int value; 
    }

    mapping(uint => Bet) public bets;
    uint public lengthBets = 0;

    constructor() public{
        MoneyLineData[2] memory moneyLineData = [MoneyLineData("Gator", 200), MoneyLineData("Miami", -100)];
        Bet memory bet;
        bet.betId = 1;
        bet.question = "Gator vs Miami";
        bet.lengthMoneyLineData = 0;
        bet.moneyLineData[bet.lengthMoneyLineData] = moneyLineData[0];
        bet.moneyLineData[bet.lengthMoneyLineData] = moneyLineData[1];
        bet.lengthMoneyLineData += moneyLineData.length;
        bets[lengthBets] = bet;
        lengthBets += 1;
    }
}

But I get this error.

Error: CompileError: /D/Workspace/Nodejs/ethereum-sports-betting/contracts/Betting.sol:32:3: TypeError: Member "moneyLineData" is not available in struct Betting.Bet memory outside of storage.
                bet.moneyLineData[bet.lengthMoneyLineData] = moneyLineData[0];
                ^---------------^

Any help would be greatly appreciated. Thank you!

1 Answer 1

1

I got a little lost in it so I thought I'd show a few patterns instead of fixing it. I think you get in trouble with a questionable data layout. Here are some patterns to help with your original question:

pragma solidity ^0.5.8;

contract MappingInStruct {

    struct Parent {
        mapping(bytes32 => Child) childrenOfTheMapping;
        Child[] childrenOfTheArray;
    }

    struct Child {
        uint value;
        string name;
    }

    Parent[] parents;

    function newParent() public {
        Parent memory p;
        parents.push(p);
        // It will get very awkward to parse inputs and map to storage here, so let's do it separately.
    }

    // As child mapping

    function newChildOfTheMapping(uint parent, bytes32 key, uint value, string memory name) public {
        Parent storage p = parents[parent]; // this will revert if out of bounds. 
        Child storage c = p.childrenOfTheMapping[key]; // overwrites existing, not sequencial, every possible key "exists" (but most default to 0).
        c.value = value;
        c.name = name;
    }

    function getChildOfTheMapping(uint parent, bytes32 key) public view returns(uint value, string memory name) {
        Child storage c = parents[parent].childrenOfTheMapping[key];
        return (c.value, c.name);
    }

    // As child array

    function newChildOfTheArray(uint parent, uint value, string memory name) public {
        Child memory c = Child({
            value: value,
            name: name
        });
        Parent storage p = parents[parent];
        p.childrenOfTheArray.push(c);
    }

    function getChildOfTheArray(uint parent, uint child) public view returns(uint value, string memory name) {
        Child storage c = parents[parent].childrenOfTheArray[child];
        return (c.value, c.name);
    }

    // array.length is a property of a dynamic array. Mapping doesn't have it. 
    function parentChildrenOfTheArrayCount(uint parent) public view returns(uint count) {
        count = parents[parent].childrenOfTheArray.length;
    }
}

This might help with the storage pointers. https://blog.b9lab.com/storage-pointers-in-solidity-7dcfaa536089

It's super important to realize that arrays, dynamic arrays and mappings are quite different. Only the [] looks the same. Make sure you know which one or combination to use so things go smoothly. Some hints over here: Are there well-solved and simple storage patterns for Solidity?

Related objects are tricky to get right. I fear this is skipping ahead much too fast, but it might save you a ton of time. https://medium.com/robhitchens/solidity-crud-epilogue-e563e794fde

Hope it helps.

3
  • Thank you very much! You are GOD! Looking at your example I found my mistake.
    – Stuxen
    Oct 27, 2019 at 3:21
  • lol. No, just a humble spirit in the bitstream. Thanks for accepting my answer. Oct 27, 2019 at 3:45
  • I know I shouldn't be asking this. But only you seem to have an immense knowledge on Ethereum. Can you answer my other question if you get time?
    – Stuxen
    Oct 29, 2019 at 0:25

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.