1

I'm trying to add more then 9 data in public struct it's showing me below error

Internal compiler error: Stack too deep, try removing local variables.

enter image description here

if I remove the public keyword from User public user; then works fine or I maintain 9 data in struct then works fine.

contract UserIndendity{

    struct User {
        address userAccount;
        address photo;
        string fName;
        string lName;
        address signature;
        string email;
        uint mno;
        string street;
        string city;
        string state;
        string country;
    }

    User public user;

    function UserIndendity(address _userAccount,address _photo,string _fName,string _lName,address _signature,string _email,uint _mno,string _street,string _city,string _state,string _country){

        user.userAccount=_userAccount;
        user.photo=_photo;
        user.fName=_fName;
        user.lName=_lName;
        user.signature=_signature;
        user.email=_email;
        user.mno=_mno;
        user.street=_street;
        user.city=_city;
        user.state=_state;
        user.country=_country;
    }
}

any one have solution for above issue?

I have also added issue on Github : Link

2

Replace all string with bytes32. The variable length string type is more "expensive".

Hope it helps.

contract UserIdentity{

    struct User {
        address userAccount;
        address photo;
        bytes32 fName;
        bytes32 lName;
        address signature;
        bytes32 email;
        uint mno;
        bytes32 street;
        bytes32 city;
        bytes32 state;
        bytes32 country;
    }

    User public user;

    function UserIndendity(address _userAccount,address _photo,bytes32 _fName,bytes32 _lName,address _signature,bytes32 _email,uint _mno,bytes32 _street,bytes32 _city,bytes32 _state,bytes32 _country){

        user.userAccount=_userAccount;
        user.photo=_photo;
        user.fName=_fName;
        user.lName=_lName;
        user.signature=_signature;
        user.email=_email;
        user.mno=_mno;
        user.street=_street;
        user.city=_city;
        user.state=_state;
        user.country=_country;
    }
}
  • if I stored as bytes32 then how to get string value? – comeback4you Mar 28 '17 at 11:41
  • The usual approach is to use client-side conversion (fast, abundant, cheap) to work things out so data fits neatly into Ethereum's 32-byte words. Web3 JavaScript API can help. See toHex(), for example. github.com/ethereum/wiki/wiki/JavaScript-API#web3tohex You can use strings sparingly. Beware, they cannot be passed between contracts at this time. So that, and the cost, are good reasons to adjust to the idea of using bytes32 in contracts. – Rob Hitchens - B9lab Mar 28 '17 at 11:48
1

When you make something "public" compiler generates accesors methods for it. From the other side, as mentiond here Error while compiling: Stack too deep, any function in solidity can have max 16 local variables. I've made one experiment:

contract UserIndendity{

    struct A
    {
        uint a1;
        uint a2;
        uint a3;
        uint a4;
        uint a5;
        uint a6;
        uint a7;
        uint a8;
        uint a9;
        uint a10;
        uint a11;
        uint a12;
        uint a13;
        uint a14;
    }

    A public a;

    struct B
    {
        string b1;
        string b2;
        string b3;
        string b4;
        string b5;
        string b6;
        string b7;
    }

    B public b;    

    struct C
    {
        bytes32 c1;
        bytes32 c2;
        bytes32 c3;
        bytes32 c4;
        bytes32 c5;
        bytes32 c6;
        bytes32 c7;
        bytes32 c8;
        bytes32 c9;
        bytes32 c10;
        bytes32 c11;
        bytes32 c12;
        bytes32 c13;
        bytes32 c14;
    }

    C public c;

    struct D
    {
        bytes d1;
        bytes d2;
        bytes d3;
        bytes d4;
        bytes d5;
        bytes d6;
        bytes d7;
    }

    D public d;
}

This code compilles well. But if you add any more member to struct, for example uint a15 to A, or string b8 to B, or bytes32 c15 to C, or bytes d8 to D the stack will become "too deep". I have an assumption, that when compiler generates accessors methods it uses 2 local variables by default, 1 local variable for every member if they are not string or bytes and 2 local variables for every string or bytes member. I think compiler just get the length of bytes or string variable to some local variable. I do not know if the assumption about generating accessor-methods is true, but you can calculate possible number of struct fields and their types as 2 + 2*string_members_count + 2*bytes_members_count + other_members_count<=16, if you want to use it as "public".

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.