Platform: Code4rena
Start Date: 14/03/2024
Pot Size: $49,000 USDC
Total HM: 3
Participants: 51
Period: 7 days
Judge: 3docSec
Id: 350
League: ETH
Rank: 25/51
Findings: 1
Award: $36.34
π Selected for report: 0
π Solo Findings: 0
π Selected for report: 0xmystery
Also found by: 0xbrett8571, 0xhacksmithh, 7ashraf, Bigsam, Circolors, IceBear, Jorgect, Koala, Limbooo, SBSecurity, Tigerfrake, ZanyBonzy, aycozynfada, cheatc0d3, cryptphi, d3e4, doublespending, foxb868, gpersoon, imare, jesjupyter, lsaudit, robriks, shealtielanz, y4y
36.3397 USDC - $36.34
According to Coinbase Docs:
Our smart wallet supports up to 256 concurrent owners. Each owner can transact independently, without sign off from any other owner.
However, the _initializeOwners()
function lack this check for the maximum number of owners allowed by the smart wallet, which is stated to be 256 concurrent owners
.
function _initializeOwners(bytes[] memory owners) internal virtual { for (uint256 i; i < owners.length; i++) { if (owners[i].length != 32 && owners[i].length != 64) { revert InvalidOwnerBytesLength(owners[i]); } if (owners[i].length == 32 && uint256(bytes32(owners[i])) > type(uint160).max) { revert InvalidEthereumAddressOwner(owners[i]); } _addOwnerAtIndex(owners[i], _getMultiOwnableStorage().nextOwnerIndex++); } }
The function iterates over the owners
array and adds each owner
without verifying if the total number of owners exceeds this limit
.
This could potentially allow more than 256 owners to be added
, which contradicts the stated contract documentation and could lead to unexpected behavior or security issues.
Manual Review
Add a check at the beginning of the function to ensure that the number of owners
being added does not exceed the maximum limit
.
Here's how you could modify the function to include this check:
function _initializeOwners(bytes[] memory owners) internal virtual { require(owners.length <= 256, "Too many owners"); // @audit Check for max limit for (uint256 i; i < owners.length; i++) { if (owners[i].length != 32 && owners[i].length != 64) { revert InvalidOwnerBytesLength(owners[i]); } if (owners[i].length == 32 && uint256(bytes32(owners[i])) > type(uint160).max) { revert InvalidEthereumAddressOwner(owners[i]); } _addOwnerAtIndex(owners[i], _getMultiOwnableStorage().nextOwnerIndex++); } }
Other
#0 - c4-pre-sort
2024-03-22T05:39:57Z
raymondfam marked the issue as sufficient quality report
#1 - c4-pre-sort
2024-03-22T05:40:35Z
raymondfam marked the issue as primary issue
#2 - raymondfam
2024-03-22T05:41:10Z
No intended cap in place indeed.
#3 - c4-sponsor
2024-03-26T14:58:19Z
wilsoncusack marked the issue as disagree with severity
#4 - wilsoncusack
2024-03-26T14:58:21Z
This is just a case of NatSpec being out of date. MultiOwnable is no longer constrained to 256 owners. Will fix
#5 - c4-sponsor
2024-03-26T14:58:23Z
wilsoncusack (sponsor) confirmed
#6 - 3docSec
2024-03-27T08:15:36Z
The 256 owners limit check is indeed nowhere to be found. However, since there is no clear impact, we should treat this finding as QA (protocol not behaving as of spec).
#7 - c4-judge
2024-03-27T08:15:46Z
3docSec changed the severity to QA (Quality Assurance)
#8 - c4-judge
2024-03-27T08:15:51Z
3docSec marked the issue as grade-a