1

I have the following smart contract:

pragma solidity ^ 0.4.2;

contract Chat {

    address public user;
    address public myAddress;
    string public message;
    string public response;
    address public owner;
    uint public time;

    function Chat(address _uw, address _a, string _m, string _r) {
        user = _uw;
        myAddress = _a;
        message = _m;
        response = _r;
        owner = msg.sender;
        time = now;
    }

    function getmyAddress() constant returns(address myAddress) {
        return myAddress;
    }

    function getMessage() constant returns(string message) {
        return message;
    }

    function getUser() constant returns(address user) {
        return user;
    }

    function getOwner() constant returns(address owner) {
        return owner;
    }

    function getResponse() constant returns(string response) {
        return response;
    }

    function getTime() constant returns(uint time) {
        return time;
    }    

    function setResponse(string r) {
        if (msg.sender == user) {
            response = r;
        }
    }

}

I would like to keep it as cheap as possible because I'm going to deploy it often. Is there any optimization to use minimum Gas as possible?

Thanks in advance!

  • The best way to save gas is to not deploy this contract multiple times. All of the functionality of this contract could be replaced with a simple struct containing the 6 variables. – Tjaden Hess Mar 24 '17 at 16:25
2

First and greatest concern is, 'I hope you're NOT going to store chat messages on the blockchain!'

As others have noted, you can wrap this in a struct. Elements less than 32 bytes are packed into storage slots as best they fit. When using a struct however, elements are packed in the order given.

Compound elements like strings will take a minimum of one slot for length which 'may' be packed with the string data if it's short enough, else will write to some hash index elsewhere in memory for at least another slot cost.

All mapping entries will take at least one slot no matter how small their type. It's with mapping that structs really shine as you can force them to pack.

// 6 elements packed into 5 32 byte slots
struct User {
    uint40 time; // cast to 5 bytes - packed with user
    address user; // 20 bytes - packed with time
    address myAddress; 20 bytes - unpacked, one slot
    address owner; // 20 bytes - unpacked, one slot

    // Strings are 32byte minimum to store length
    string message; // 32 bytes minimum to store length
    string response; // 32 bytes minimum to store length
}

So with the above we can have something like:

mapping (address => User) public chats;

And this will generate a public accessor function with a signature of:

chats(address _param);

The return value however will be an unnamed array of struct values in the order of the struct elements.

--edit for secondary question---

Here's one way to load up a struct variable. I'm showing it in the context of your code, but the apparent intention of your code does seem to me quite irresponsible.

contract Chat
{
    struct User {
        uint40 time;
        address user;
        address myAddress;
        address owner;
        string message;
        string response;
    }

    User public message;

    function Chat(address _uw, address _a, string _m, string _r) 
    {
        message = User ({
            user: _uw,
            myAddress: _a,
            message: _m,
            response:_r,
            owner: msg.sender,
            time: now
            });
    }
}
  • Thanks for your answer. But how can I set all mapping entries through a constructor? – FrenchieiSverige Mar 28 '17 at 7:30
  • 1
    Please see edits – o0ragman0o Mar 28 '17 at 8:06
  • Thanks. And do not worry, I'll NOT store chat messages on the blockchain. This was just an example. – FrenchieiSverige Mar 28 '17 at 8:40
  • I tried to measure this and there was no gas savings. What am I missing? gist.github.com/raineorshine/5816c7f647e0090fc3ac52b9d036bb99 – Raine Revere Apr 24 '17 at 16:02
  • 1
    @raine The main issue was the unnecessary bytecode in the getters, not so much the var vs struct. Your packing ends up the same for both vars and struct so there's not a whole lot of difference in gas (the ~106 difference likely being the call table). For unstructured state variables, I believe the compiler makes a best effort, whereas for structs it simply packs in order of the members. – o0ragman0o Apr 25 '17 at 9:19
3
  1. You can get rid of all your get* methods since your fields are already public: myContract.user() will act just like myContract.getUser().

  2. It looks like a candidate for a struct. That would be gas-cheaper.

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.