3

I know that I can't get the return value from a transaction (How to get values returned by non constant transaction functions?), and non-constant functions have return value because they can be called from another contract (What's the point of returning a value in a non-constant function?).

For example in the following contract the function getUserData is non-constant because it modifies array allData in contract storage:

pragma solidity ^0.4.15;

contract Storage {
  mapping (uint => uint) public users;
  uint[] public allData;

  event SetUserData(uint userId, uint data);

  function setUserData(uint userId, uint data) public {
    require(users[userId] == 0);
    // Stores user data
    users[userId] = data;
    // Stores user id
    allData.push(userId);
    SetUserData(userId, data);
  }

  function getUserData(uint userId) public returns (uint[] data) {
    if (users[userId] != 0) {
      // Will return user data but modifies contract storage
      allData.length = 0; // Ignore previous data
      allData.push(users[userId]);
      return allData;
    } else {
      return data;
    }
  }
}

But when I call a non-contant function from javascript I do not get an error, instead I got the expected return value.

Testing in a private network with geth v1.7.1 this test passes, but with testrpc v4.1.3 it fails.

const Storage = artifacts.require("./Storage.sol");

contract('Storage', function(accounts) {
  let storage;
  before(async () => {
    storage = await Storage.deployed();
  });
  it("Set user data", async () => {
    // Stores user data
    await storage.setUserData(4321, 7890);
    // Get user data 
    const data = await storage.getUserData.call(4321);
    assert.equal(data[0], 7890, 'Return user data');
    // Check contract storage is not modified
    const allData = await storage.allData.call(0);
    assert.equal(allData, 4321, 'Return userId');
  });
});

Is is defined behavior to eth_call a non-constant function from javascript or it is an implementation detail of geth?

I'd like it to be defined behavior, but I understand that an implementation can return an error if I call non-constant function.

One minor difference is that in a constant function I can allocate arrays in memory, but I cannot dynamically grow them. But if I can use arrays in storage I can use push to grow them dynamically.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.