solidity – How to Read Struct Values in Solidity Contract?

consolecontract-invocationsoliditytruffle

I have developed the following smart contract and try to test it via the truffle js console:

pragma solidity ^0.4.2;

contract AddressRatings {

struct Rating {
    mapping ( address => uint8 ) ratings;
    uint256 amtOfRatings;
    uint256 sumOfRatings;
    uint8 average;
}

mapping ( address => Rating ) public ratings;

function rateAddress (address _addr, uint8 _rating) external {
    require(_rating > 0 && _rating < 6); // only ratings from 1 to 5 are allowed
    require(ratings[_addr].ratings[msg.sender] == 0); // a sender can rate someone else only once
    ratings[_addr].ratings[msg.sender] = _rating;
    ratings[_addr].amtOfRatings++;
    ratings[_addr].sumOfRatings += _rating;
    ratings[_addr].average = uint8(ratings[_addr].sumOfRatings/ratings[_addr].amtOfRatings);
}

}

I'm able to get an instance of the contract and call the method rateAddress. Also I can retrieve an object of ratings mapping. However, I don't know how to read the attributes of the returned Rating struct.

Whatever I try returns undefined e.g. ratingsObj1, ratingsObj['average'], ratingsObj.average

enter image description here

Also, it seems that the mapping within the struct does not to work, although it compiles…

Any hint is appreciated!

P.S.: Suggestions how to make this contract more efficient are very welcome.

Best Answer

The problem, is that your struct Rating contains a mapping. Solidity cannot return mapping from functions, as it has no idea how large it is. It can, however return the individual entries the keys are provided. You should probably keep track of whether an address has rated an address in another way. Here's how I would do it:

pragma solidity ^0.4.23;

contract AddressRatings {

    struct Rating {
        uint256 amtOfRatings;
        uint256 sumOfRatings;
        uint8 average;
    }

    mapping(address => mapping(address => uint8)) public ratingsPerAddress;

    mapping (address => Rating ) public ratings;

    function rateAddress (address _addr, uint8 _rating) external {
        require(_rating > 0 && _rating < 6); // only ratings from 1 to 5 are allowed
        require(ratingsPerAddress[_addr][msg.sender] == 0); // a sender can rate someone else only once

        ratingsPerAddress[_addr][msg.sender] = _rating;

        ratings[_addr].amtOfRatings++;
        ratings[_addr].sumOfRatings += _rating;
        ratings[_addr].average = uint8(ratings[_addr].sumOfRatings/ratings[_addr].amtOfRatings);
    }

}
Related Topic