Platform: Code4rena
Start Date: 22/02/2022
Pot Size: $30,000 USDC
Total HM: 1
Participants: 22
Period: 3 days
Judge: leastwood
Id: 93
League: ETH
Rank: 14/22
Findings: 1
Award: $98.17
🌟 Selected for report: 0
🚀 Solo Findings: 0
98.1684 USDC - $98.17
bool
s for storage incurs overhead// Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled.
mapping(address => mapping(address => bool)) internal representatives;
external
rather than public
function initialize(uint96 _lockUntil) public {
> 0
costs more gas than != 0
when used on uints in a require()
statementrequire(_amount > 0, "TWABDelegator/amount-gt-zero");
<array>.length
should not be looked up in every loop of a for-loopEven memory arrays incur the overhead of bit tests and bit shifts to calculate the array length
for (uint256 i = 0; i < _data.length; i++) {
for (uint256 i = 0; i < calls.length; i++) {
++i
/i++
should be unchecked{++i}
/unchecked{++i}
when it is not possible for them to overflow, as is the case when used in for- and while-loopsfor (uint256 i = 0; i < _data.length; i++) {
for (uint256 i = 0; i < calls.length; i++) {
++i
costs less gas than ++i
, especially when it's used in for-loops (--i
/i--
too)for (uint256 i = 0; i < _data.length; i++) {
for (uint256 i = 0; i < calls.length; i++) {
for (uint256 i = 0; i < _data.length; i++) {
for (uint256 i = 0; i < calls.length; i++) {
Doing so saves the cost of allocating the function selector, and the cost of the jump when the function is called.
function _requireDelegatorNotZeroAddress(address _delegator) internal pure { require(_delegator != address(0), "TWABDelegator/dlgtr-not-zero-adr"); }
Even memory arrays incur the overhead of bit tests and bit shifts to calculate the array length. calls.length
can be cached
bytes[] memory response = new bytes[](calls.length); for (uint256 i = 0; i < calls.length; i++) {
#0 - PierrickGT
2022-03-01T23:03:00Z
Using bools for storage incurs overhead
Not clear which value we should store instead. uint256(1)
?
It is also easier and much more legible to store a boolean instead of comparing a uint256
to 1
in the _requireDelegatorOrRepresentative
function: https://github.com/pooltogether/v4-twab-delegator/blob/2b6d42506187dd7096043e2dfec65fa06ab18577/contracts/TWABDelegator.sol#L583
Functions not called by the contract itself should be external rather than public Using > 0 costs more gas than != 0 when used on uints in a require() statement
Duplicate of https://github.com/code-423n4/2022-02-pooltogether-findings/issues/15
<array>.length should not be looked up in every loop of a for-loop ++i costs less gas than ++i, especially when it's used in for-loops (--i/i-- too) It costs more gas to initialize variables to zero than to let the default of zero be applied Using stack copies of variables when repeated access is required uses less gas
Duplicate of https://github.com/code-423n4/2022-02-pooltogether-findings/issues/9
It costs less gas to inline the code of functions that are only called once
PR: https://github.com/pooltogether/v4-twab-delegator/pull/26
++i/i++ should be unchecked{++i}/unchecked{++i} when it is not possible for them to overflow, as is the case when used in for- and while-loops
Duplicate of https://github.com/code-423n4/2022-02-pooltogether-findings/issues/36