0

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.

1

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);
    }

}
  • Thank you for your suggestion! I'm still not able to retrieve the values from the mappings via the javascript console (see screenshot). Do you have any advice on that? – Mindful May 1 '18 at 7:35
  • You should call app.ratings like this if you want to retrieve the first element for the first account: app.ratings(web3.eth.accounts[0], 0) – Henk May 1 '18 at 7:37
0

Using a promise to retrieve a Rating object, allowed me to access the attributes with an index. toNumber function finally returns the value :)

enter image description here

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.