Solidity – Compare Structs and Arrays with Keccak256 to Save Gas

arrayscontract-developmenthashkeccaksolidity

Just working on a solidity code last day, I figured out that apart of comparing bytes, strings etc…

The Keccak256 will be the perfect solution for comparing large arrays or big structs. Because as the Hash functions properties say:

Given x and y with the assumption (x != y) => We can assume that H(x) != H(y)

So comparing it's hashes will make us spend a lot less Gas than iterating the array, and demonstrate us that they are or no equal (doesn't matter on which index).

So with an example:

Let's supose that we have 2 large arrays of the same type. Will it be possible to do something as:

Assert.equal(keccak256(array1)), keccak256(array2));

That is what you do in order to compare strings for example. (That if I'm not wrong, are interpreted as arrays at the end).

In order to don't do something like:

Assert.equal(array1[i], array2[i]); 
//Implemented on a for loop from i=0 to i=minlength(arr1,arr2)

Obviously, other implementations as adding mappings or stuff like that can solve quite well the problem, but I'm interested on knowing if there's any trick that allows you to compare this types of stuctures with the keccak256().

Thanks.

Best Answer

Yes there is!

As keccak256 in Solidity yieds a bytes32 value, you could just compare the outcomes using ==.

An example:

pragma solidity 0.4.24;

contract KeccakCompare {
    struct Example {
        uint256 age;
        bytes32 name;
    }

    Example[] public examples;

    function pushExample(uint256 _age, bytes32 _name) external {
        examples.push(Example({
            age: _age,
            name: _name
        }));
    }

    function equals(uint256 _firstIndex, uint256 _secondIndex) external view returns (bool) {
        return equals(examples[_firstIndex], examples[_secondIndex]);
    }

    function equals(Example storage _first, Example storage _second) internal view returns (bool) {
        // Just compare the output of hashing all fields packed
        return(keccak256(abi.encodePacked(_first.age, _first.name)) == keccak256(abi.encodePacked(_second.age, _second.name)));
    }
}
Related Topic