Solidity – Gas Optimization for Smart Contracts

contract-designgassolidity

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!

Best Answer

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
            });
    }
}
Related Topic