Skip to main content
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
possible solution, new question
Source Link

EDIT

I figured out what the error was. I implemented the above code in my project and it worked fine. Then I took my original code and tried to implement the same thing but got the same errors. The problem was in some functions I was trying to return a value from the data storage contract to the child user contract before setting a value. Here is an example. If ExampleDataStorage had a function that returns a said value, e.g.,

function returnRandomValue() public view returns(uint) {
    return somethingFromStorage[0];

}

and I call this function from the child contract like this:

function _setAvatarNumber(uint8 _newAvatarNumber) public {
    uint _something = _storage.returnRandomValue();
    _storage.setAvatarNumber(_newAvatarNumber, msg.sender);
    emit avatarSet(_contractName, _newAvatarNumber);
}

then for some reason the error occurs. So for me to fix it, I can just make sure to not call any getters from within the child contract from the parent contract. However, in some cases this might not be ideal as in the future I would need contract interaction, specifically getting the value from another contract's storage (called from another contract) and then using that return value for something else. Does anyone know why this happens?

EDIT

I figured out what the error was. I implemented the above code in my project and it worked fine. Then I took my original code and tried to implement the same thing but got the same errors. The problem was in some functions I was trying to return a value from the data storage contract to the child user contract before setting a value. Here is an example. If ExampleDataStorage had a function that returns a said value, e.g.,

function returnRandomValue() public view returns(uint) {
    return somethingFromStorage[0];

}

and I call this function from the child contract like this:

function _setAvatarNumber(uint8 _newAvatarNumber) public {
    uint _something = _storage.returnRandomValue();
    _storage.setAvatarNumber(_newAvatarNumber, msg.sender);
    emit avatarSet(_contractName, _newAvatarNumber);
}

then for some reason the error occurs. So for me to fix it, I can just make sure to not call any getters from within the child contract from the parent contract. However, in some cases this might not be ideal as in the future I would need contract interaction, specifically getting the value from another contract's storage (called from another contract) and then using that return value for something else. Does anyone know why this happens?

Source Link

Web3 method call returning unexpected value with certain smart contract setup

I have tried to implement a persistent data storage with smart contracts as seen with the following code (this is an example that mimics what my actual code does). I have a data storage contract with a mapping of contract addresses to another mapping of more data so that each calling contract can have access to their own set of data, taken from this article https://medium.com/quillhash/how-to-write-upgradable-smart-contracts-in-solidity-d8f1b95a0e9a. Setters can only be set for msg.sender, i.e., the calling contract. Getters can be accessed by anyone, e.g. from "OtherContract" below since he has access to the "UserContract" address. (Side note: I inherit from SharedEvents since I do something similar in my actual code and I include this here just in case this might affect the weird behavior I am seeing.)

pragma solidity ^0.5.0;

contract ExampleDataStorage {

struct UserProfile {
    string username;
    string department;
    uint8 avatarNumber;
    uint40 totalSteps;
    mapping(uint32 => uint32) userStepInfo;
    uint32 lastSyncDate;
}

mapping(address => mapping(address => UserProfile)) _userProfile;

function setAvatarNumber(uint8 _avatarNumber, address _userAddress) public {
    _userProfile[msg.sender][_userAddress].avatarNumber = _avatarNumber;
}

function getAvatarNumber(address _contractAddress, address _userAddress) public view returns(uint8) {
    return _userProfile[_contractAddress][_userAddress].avatarNumber;
}

}

contract SharedEvents {

constructor () public {}

event avatarSet(string _contractName, uint8 _avatar);

}


contract UserContract is SharedEvents {

ExampleDataStorage _storage;
string _contractName = "UserContract";

constructor (address _exampleDataStorageAddress) public payable {
    _storage = ExampleDataStorage(_exampleDataStorageAddress);
}

function _setAvatarNumber(uint8 _newAvatarNumber) public {
    _storage.setAvatarNumber(_newAvatarNumber, msg.sender);
    emit avatarSet(_contractName, _newAvatarNumber);
}

function _getAvatarNumber() public view returns(uint8) {
    return _storage.getAvatarNumber(address(this), msg.sender);
}

}


contract OtherContract is SharedEvents {

ExampleDataStorage _storage;
address _userContractAddress;

constructor (address _exampleDataStorageAddress, address _userContractAddressParam) public payable {
    _storage = ExampleDataStorage(_exampleDataStorageAddress);
    _userContractAddress = _userContractAddressParam;
}

function _getAvatarNumber() public view returns(uint8) {
    return _storage.getAvatarNumber(_userContractAddress, msg.sender);
}

}

Below is the truffle migration code.

module.exports = function(deployer) {
    deployer.deploy(ExampleDataStorage)
    .then(() => {
        return deployer.deploy(UserContract, ExampleDataStorage.address)
    })
    .then(() => {
        return deployer.deploy(OtherContract, ExampleDataStorage.address, UserContract.address)
    })
}

When this is run in remix, everything works fine. When I deploy with truffle all contracts are compiled. When I use web3 is when I see problems occur. I am using web3@^1.0.0-beta.33 and truffle@^4.1.14. When I use web3 and call the setavatar function from UserContract, I get no errors. When I use web3 and call the getter from the ExampleDataStorage contract (in a function like below), I get the default value 0 for uint8 instead of the value I set before.

getAvatarNumber (address) {
    return this.contractHandler.methods.getAvatarNumber(this.UserContractAddress, address).call()
}

I am sure that I am passing in the correct contract addresses in truffle so I have no idea why I am not correctly accessing the data I should be getting. Inside my actual code, I also added a test function inside UserContract that prints out both the ExampleDataStorage and UserContract addresses to make sure I am using the correct addresses when setting and getting. Any help would be greatly appreciated. Thank you very much.