18

This question already has an answer here:

When I set more than eight values as function’s return , the following error occurred. ( When the num of values is less than seven, the error didn’t occur)

Could you tell me how can I get more than 8 return values by a function?

Code

struct  User{
    uint256 uuid;
    bytes32 first_name;
    bytes32 last_name;
    bytes32 sex;
    bytes32 age;
    bytes32 birth_day;
    bytes32 address;
    bytes32 mail_address;
    bytes32 phone_number;
 }

function getUser(uint256 uuid) constant returns (bytes32, bytes32, bytes32, bytes32, bytes32, bytes32, bytes32, bytes32) {
    return (
    users[uuid].first_name,
    users[uuid].last_name,
    users[uuid].sex,
    users[uuid].age,
    users[uuid].birth_day,
    users[uuid].address,
    users[uuid].mail_address,
    users[uuid].phone_number
    );
}

Error

Compiler error: Stack too deep, try removing local variables.
        users[uuid].phone_number

marked as duplicate by Richard Horrocks, galahad, eth Jul 23 '16 at 1:11

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • Marked this as a duplicated, but I'm surprised the limit in your case is only 7 variables. There must be a limit on combined stack variable size, rather than just a variable count. The solution in the other thread still holds: split your functions into smaller functions. – Richard Horrocks Jul 22 '16 at 13:14
  • 3
    Same error message, but caused by a different use, has a different limitation of variables due to the struct, has a code, everything is better about this question. This is not a duplicate. – saitam Jul 7 '18 at 7:53
17

Update Sep 18 2018

I just re-tested and the following works:

pragma solidity ^0.4.25;

contract Test {

    struct  User{
        uint256 uuid;
        bytes32 first_name;
        bytes32 last_name;
        bytes32 sex;
        bytes32 age;
        bytes32 birth_day;
        bytes32 addr;
        bytes32 mail_address;
        bytes32 phone_number;
    }

    mapping(uint256 => User) users;

    function getUser(uint256 uuid) public constant returns (bytes32, bytes32, bytes32, bytes32, bytes32, bytes32, bytes32, bytes32) {
        User memory u = users[uuid];
        return (
            u.first_name,
            u.last_name,
            u.sex,
            u.age,
            u.birth_day,
            u.addr,
            u.mail_address,
            u.phone_number
        );
    }
}

See also @pipermerriam's usage of arrays to use lots of variables (https://github.com/ethereum-alarm-clock/ethereum-alarm-clock/blob/master/contracts/Library/RequestLib.sol#L86-L130):

function initialize(
    Request storage self,
    address[4]      _addressArgs,
    uint[12]        _uintArgs,
    bytes           _callData
) 
    public returns (bool)
{
    address[6] memory addressValues = [
        0x0,                // self.claimData.claimedBy
        _addressArgs[0],    // self.meta.createdBy
        _addressArgs[1],    // self.meta.owner
        _addressArgs[2],    // self.paymentData.feeRecipient
        0x0,                // self.paymentData.bountyBenefactor
        _addressArgs[3]     // self.txnData.toAddress
    ];

    bool[3] memory boolValues = [false, false, false];

    uint[15] memory uintValues = [
        0,                  // self.claimData.claimDeposit
        _uintArgs[0],       // self.paymentData.fee
        0,                  // self.paymentData.feeOwed
        _uintArgs[1],       // self.paymentData.bounty
        0,                  // self.paymentData.bountyOwed
        _uintArgs[2],       // self.schedule.claimWindowSize
        _uintArgs[3],       // self.schedule.freezePeriod
        _uintArgs[4],       // self.schedule.reservedWindowSize
        _uintArgs[5],       // self.schedule.temporalUnit
        _uintArgs[6],       // self.schedule.windowSize
        _uintArgs[7],       // self.schedule.windowStart
        _uintArgs[8],       // self.txnData.callGas
        _uintArgs[9],       // self.txnData.callValue
        _uintArgs[10],      // self.txnData.gasPrice
        _uintArgs[11]       // self.claimData.requiredDeposit
    ];

    uint8[1] memory uint8Values = [
        0
    ];

    require(deserialize(self, addressValues, boolValues, uintValues, uint8Values, _callData));

    return true;
}

It does not cost anything to call constant functions, so just split your getUser(...) function into two or more functions.

For example:

function getUserName(uint256 uuid) constant returns (bytes32, bytes32) {
    return (
    users[uuid].first_name,
    users[uuid].last_name
    );
}

function getUserDetails(uint256 uuid) constant returns (bytes32, bytes32, bytes32, bytes32, bytes32, bytes32) {
    return (
    users[uuid].sex,
    users[uuid].age,
    users[uuid].birth_day,
    users[uuid].address,
    users[uuid].mail_address,
    users[uuid].phone_number
    );
}

Further details at Error while compiling: Stack too deep

  • 5
    I can't believe this worked. The stack can only be 7 steps deep :/ . :D Thank you! Such simple much wow :D – Pramesh Bajracharya Feb 25 '18 at 9:05
  • 2
    There also might be a problem when struct is too big ( too many variables ). Then you will also get this error message when creating struct. The solution is similar. Split structure into two smaller. Worked for me. – Rob Magier Jul 28 '18 at 22:48
  • Have a look at how the Ethereum Alarm Clock handles many variables - github.com/ethereum-alarm-clock/ethereum-alarm-clock/blob/… – The Officious BokkyPooBah Jul 30 '18 at 7:20

Not the answer you're looking for? Browse other questions tagged or ask your own question.