I made two sample contracts using the provided code in Remix:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/* Deployment:
gas 291003 gas
transaction cost 253106 gas
execution cost 185426 gas
First `setValues()`:
gas 102048 gas
transaction cost 88737 gas
execution cost 67253 gas
Second `setValues()`:
gas 33393 gas
transaction cost 29037 gas
execution cost 7553 gas
`readValues()`: 7015 gas
*/
contract A {
uint128 public x;
uint256 public y;
uint128 public z;
function setValues(uint128 _x, uint _y, uint128 _z) public {
x = _x;
y = _y;
z = _z;
}
function readValues() public view returns(uint128, uint256, uint128) {
return (x,y,z);
}
}
/* Deployment:
gas 291003 gas
transaction cost 253106 gas
execution cost 185426 gas
First `setValues()`:
gas 76870 gas
transaction cost 66843 gas
execution cost 45359 gas
Second `setValues()`:
gas 31100 gas
transaction cost 27043 gas
execution cost 5559 gas
`readValues()`: 5065 gas
*/
contract B {
uint128 public x;
uint128 public y;
uint256 public z;
function setValues(uint128 _x, uint128 _y, uint _z) public {
x = _x;
y = _y;
z = _z;
}
function readValues() public view returns(uint128, uint128, uint256) {
return (x,y,z);
}
}
The deployment cost between the two contracts was identical, however, once I started making function calls, the differences became apparent.
contract A
costs more when writing to hot and cold storage, as well as making a view
call to the values.
Taking it a little further, I added an function to each contract that only sets the value for the first uint x
.
function setValue(uint128 _x) public {
x = _x;
}
Surprisingly, contract B
's function call cost more gas:
Contract A:
gas 50351 gas
transaction cost 43783 gas
execution cost 22579 gas
Contract B:
gas 50376 gas
transaction cost 43805 gas
execution cost 22601 gas
I'm not sure why, but I'm assuming it's caused by having to set a specific part of the zero storage slot's value as opposed to simply setting the entire value for storage slot zero's variable.
Kind of like tip-toeing around uint y
as to not wake it up.