1

I'm trying to create a contract where I can save and then call a person's 'first name', 'last name' and 'age' within the truffle console. I'm able to save using the addPerson method, but every time I call method getPeople I receive an empty array. Here is the contact.

pragma solidity ^0.4.4;

  contract People {

    Person[] public people;

    struct Person {
      bytes32 firstName;
      bytes32 lastName;
      uint age;

    }
    function addPerson(bytes32 _firstName, bytes32 _lastName, uint _age) returns (bool success) {

      Person memory newPerson;
      newPerson.firstName = _firstName;
      newPerson.lastName = _lastName;
      newPerson.age = _age;

      people.push(newPerson);
      return true;
    }
    function getPeople() constant returns (bytes32[], bytes32[],uint[]) {

      uint length = people.length;

      bytes32[] memory firstNames = new bytes32[](length);
      bytes32[] memory lastNames = new bytes32[](length);
      uint[] memory ages = new uint[](length);

      for(uint i=0; i < people.length; i++) {
        Person memory currentPerson;
        currentPerson = people[i];

        firstNames[i] = currentPerson.firstName;
        lastNames[i] = currentPerson.lastName;
        ages[i] = currentPerson.age;
      }
      return (firstNames, lastNames, ages);

    }

  }

It seems to be working. I was able to compile and migrate it using truffle compile and truffle migrate.

I'm running testrpc in the terminal. And it seems like my transactions are accurately being recorded.

enter image description here

I'm interacting with the contract via truffle console. When I enter in the command People.deployed().abi and People.deployed().address() I get a value.

enter image description here

I can enter info using the addPerson method:

People.deployed.addPerson('Darlene', 'Brown', 25)

I don't know why when I call getPeople I get back an empty array

truffle(default)> People.deployed().getPeople().then(console.log) [ [], [], [] ] undefined

  • Have you tried accessing a specific person manually? I'm not familiar with Truffle, but People.deployed().people(0) should return the first Person as an array. – Matthew Schmidt Jan 21 '17 at 19:51
  • It seems to be working when I tried the code in browser-solidity. It's possible it's a truffle-specific issue, or has to do with compiler versions. – Matthew Schmidt Jan 21 '17 at 19:55
  • When I tried accessing the first value value People.deployed().people(0).then(console.log) I get this as a result: [ '0x', '0x', { [String: '0'] s: 1, e: 0, c: [ 0 ] } ] Next, I will try the code in browser-solidity. – pkafei Jan 21 '17 at 20:34
  • That would indicate people aren't being added. All of those values are basically 0. But looks like your question's already been answered. – Matthew Schmidt Jan 22 '17 at 21:05
1

Variable length values such as dynamic arrays and strings can be returned from functions in the same contract, but they can't be successfully used for communication between contracts or the outside world because the ABI requires strictly fixed-length arguments.

The idea of returning the whole list is an anti-pattern, in my opinion. I agree with Mathew that the public people getter should work as expected, or you can add an explicit function. Avoid looping where possible (nearly always where data storage is concerned) because of gas cost and other factors.

Below I added a function to also return the array length for people so an external client can know how many rows exist. The client can do the looping operation, if needed, such as getting the whole list.

This "add only" interable storage pattern can be extended to support "delete" with a few more lines if you need that as well.

pragma solidity ^0.4.4;

contract People {

    Person[] public people;

    struct Person {
      bytes32 firstName;
      bytes32 lastName;
      uint age;
    }

    function addPerson(bytes32 firstName, bytes32 lastName, uint age) returns (bool success) {

      Person memory newPerson;
      newPerson.firstName = firstName;
      newPerson.lastName = lastName;
      newPerson.age = age;

      people.push(newPerson);
      return true;
    }

    function getPerson(uint index) constant returns(bytes32 firstName, bytes32 lastName, uint age) {
        // return value should be an array with three elements
        return (people[index].firstName, people[index].lastName, people[index].age);
    }

    function getPersonCount() constant returns(uint count) {
        return people.length;
    }

}

Hope it helps.

0

I was able to run this code correctly on Truffle v.3.x where the People.deployed() object returns a promise. Not sure if this applies to your version of Truffle (looks like v.2.x) but you're missing the double parentheses on your deployed function call here: People.deployed.addPerson('Darlene', 'Brown', 25) which may be the reason you are not able to add values to people.

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.