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: 30/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
The same address list should give the same address based on the assumption that if the parameters passed are the same but the create account in the factory will deploy 2 different address if the same address are passed when the position of the address are switched with the same nonce. This error will break the already established fact that the same owners list and nonce should give the same address and revert without creating another account. But will not follow this assertion hence invalidating it. The impact of this issue is critical as it undermines the expected behavior of the system regarding account creation. Specifically, it disrupts the deterministic nature of account address generation, potentially leading to confusion, data inconsistencies, and security concerns. If left unaddressed, this issue could compromise the integrity and reliability of the system.
The vulnerability can be demonstrated through the following test scenario:
The provided test scenario confirms that the system behaves inconsistently when the order of addresses in the owner list is changed, leading to the creation of multiple accounts for the same owner.
function setUp() public { account = new CoinbaseSmartWallet(); factory = new CoinbaseSmartWalletFactory(address(account)); owners.push(abi.encode(address(1))); owners.push(abi.encode(address(2))); }
function test_createAccountDeploysToPredeterminedAddress() public { address p = factory.getAddress(owners, 0); CoinbaseSmartWallet a = factory.createAccount{value: 1e18}(owners, 0); assertEq(address(a), p); owners.pop(); owners.pop(); owners.push(abi.encode(address(2))); owners.push(abi.encode(address(1))); address pp = factory.getAddress(owners, 0); CoinbaseSmartWallet aa = factory.createAccount{value: 1e18}(owners,0); assertEq(address(aa), pp); assertEq(address(aa), address(a));
1 gives 0x761f8B0050e1C64663cdf67b163e139e74f2DDAd::isOwnerAddress;
2 gives0x00b70D9C493558d6F201966236B643EE44a43f30::isOwnerAddress;
Ran 1 test for test/SmartWallet/CoinbaseSmartWalletFactory.t.sol:CoinbaseSmartWalletFactoryTest [FAIL. Reason: assertion failed] test_createAccountDeploysToPredeterminedAddress() (gas: 545531) Logs: Error: a == b not satisfied [address] Left: 0x00b70D9C493558d6F201966236B643EE44a43f30 Right: 0x761f8B0050e1C64663cdf67b163e139e74f2DDAd Traces: [545531] CoinbaseSmartWalletFactoryTest::test_createAccountDeploysToPredeterminedAddress() ββ [1979] CoinbaseSmartWalletFactory::getAddress([0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000002], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) [staticcall] β ββ β 0x761f8B0050e1C64663cdf67b163e139e74f2DDAd ββ [241054] CoinbaseSmartWalletFactory::createAccount{value: 1000000000000000000}([0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000002], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) β ββ [34337] β new <unknown>@0x761f8B0050e1C64663cdf67b163e139e74f2DDAd β β ββ β 95 bytes of code β ββ [168692] 0x761f8B0050e1C64663cdf67b163e139e74f2DDAd::initialize([0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000002]) β β ββ [165886] CoinbaseSmartWallet::initialize([0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000002]) [delegatecall] β β β ββ emit AddOwner(index: 0, owner: 0x0000000000000000000000000000000000000000000000000000000000000001) β β β ββ emit AddOwner(index: 1, owner: 0x0000000000000000000000000000000000000000000000000000000000000002) β β β ββ β () β β ββ β () β ββ β 0x761f8B0050e1C64663cdf67b163e139e74f2DDAd ββ [1979] CoinbaseSmartWalletFactory::getAddress([0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000001], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) [staticcall] β ββ β 0x00b70D9C493558d6F201966236B643EE44a43f30 ββ [238554] CoinbaseSmartWalletFactory::createAccount{value: 1000000000000000000}([0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000001], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) β ββ [34337] β new <unknown>@0x00b70D9C493558d6F201966236B643EE44a43f30 β β ββ β 95 bytes of code β ββ [166192] 0x00b70D9C493558d6F201966236B643EE44a43f30::initialize([0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000001]) β β ββ [165886] CoinbaseSmartWallet::initialize([0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000001]) [delegatecall] β β β ββ emit AddOwner(index: 0, owner: 0x0000000000000000000000000000000000000000000000000000000000000002) β β β ββ emit AddOwner(index: 1, owner: 0x0000000000000000000000000000000000000000000000000000000000000001) β β β ββ β () β β ββ β () β ββ β 0x00b70D9C493558d6F201966236B643EE44a43f30 ββ emit log(val: "Error: a == b not satisfied [address]") ββ emit log_named_address(key: " Left", val: 0x00b70D9C493558d6F201966236B643EE44a43f30) ββ emit log_named_address(key: " Right", val: 0x761f8B0050e1C64663cdf67b163e139e74f2DDAd) ββ [0] VM::store(VM: [0x7109709ECfa91a80626fF3989D68f67F5b1DD12D], 0x6661696c65640000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000001) β ββ β () ββ β () Test result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 2.07ms Ran 1 test suite in 2.07ms: 0 tests passed, 1 failed, 0 skipped (1 total tests) Failing tests: Encountered 1 failing test in test/SmartWallet/CoinbaseSmartWalletFactory.t.sol:CoinbaseSmartWalletFactoryTest [FAIL. Reason: assertion failed] test_createAccountDeploysToPredeterminedAddress() (gas: 545531)
when the list of owner was enlogated the system upholds this assertion
function setUp() public { account = new CoinbaseSmartWallet(); factory = new CoinbaseSmartWalletFactory(address(account)); owners.push(abi.encode(address(1))); owners.push(abi.encode(address(2))); owners.push(abi.encode(address(3))); owners.push(abi.encode(address(4))); }
function test_createAccountDeploysToPredeterminedAddress() public { address p = factory.getAddress(owners, 0); CoinbaseSmartWallet a = factory.createAccount{value: 1e18}(owners, 0); assertEq(address(a), p); owners.pop(); owners.pop(); owners.push(abi.encode(address(2))); owners.push(abi.encode(address(1))); owners.push(abi.encode(address(3))); owners.push(abi.encode(address(4))); address pp = factory.getAddress(owners, 0); CoinbaseSmartWallet aa = factory.createAccount{value: 1e18}(owners,0); assertEq(address(aa), pp); assertEq(address(aa), address(a));
Ran 1 test for test/SmartWallet/CoinbaseSmartWalletFactory.t.sol:CoinbaseSmartWalletFactoryTest [FAIL. Reason: AlreadyOwner(0x0000000000000000000000000000000000000000000000000000000000000002)] test_createAccountDeploysToPredeterminedAddress() (gas: 801156) Traces: [792756] CoinbaseSmartWalletFactoryTest::test_createAccountDeploysToPredeterminedAddress() ββ [2755] CoinbaseSmartWalletFactory::getAddress([0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000003, 0x0000000000000000000000000000000000000000000000000000000000000004], 0) [staticcall] β ββ β 0xcd6C85B8890C999EE10eF30e9ce0aC831A7B6E58 ββ [385457] CoinbaseSmartWalletFactory::createAccount{value: 1000000000000000000}([0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000003, 0x0000000000000000000000000000000000000000000000000000000000000004], 0) β ββ [34337] β new <unknown>@0xcd6C85B8890C999EE10eF30e9ce0aC831A7B6E58 β β ββ β 95 bytes of code β ββ [311578] 0xcd6C85B8890C999EE10eF30e9ce0aC831A7B6E58::initialize([0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000003, 0x0000000000000000000000000000000000000000000000000000000000000004]) β β ββ [308736] CoinbaseSmartWallet::initialize([0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000003, 0x0000000000000000000000000000000000000000000000000000000000000004]) [delegatecall] β β β ββ emit AddOwner(index: 0, owner: 0x0000000000000000000000000000000000000000000000000000000000000001) β β β ββ emit AddOwner(index: 1, owner: 0x0000000000000000000000000000000000000000000000000000000000000002) β β β ββ emit AddOwner(index: 2, owner: 0x0000000000000000000000000000000000000000000000000000000000000003) β β β ββ emit AddOwner(index: 3, owner: 0x0000000000000000000000000000000000000000000000000000000000000004) β β β ββ β () β β ββ β () β ββ β 0xcd6C85B8890C999EE10eF30e9ce0aC831A7B6E58 ββ [3532] CoinbaseSmartWalletFactory::getAddress([0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000003, 0x0000000000000000000000000000000000000000000000000000000000000004], 0) [staticcall] β ββ β 0x5f01e364aA7bca426802DD1ac2275371Dc84eaE9 ββ [245225] CoinbaseSmartWalletFactory::createAccount{value: 1000000000000000000}([0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000003, 0x0000000000000000000000000000000000000000000000000000000000000004], 0) β ββ [34337] β new <unknown>@0x5f01e364aA7bca426802DD1ac2275371Dc84eaE9 β β ββ β 95 bytes of code β ββ [169896] 0x5f01e364aA7bca426802DD1ac2275371Dc84eaE9::initialize([0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000003, 0x0000000000000000000000000000000000000000000000000000000000000004]) β β ββ [169507] CoinbaseSmartWallet::initialize([0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000000000000000000000000000003, 0x0000000000000000000000000000000000000000000000000000000000000004]) [delegatecall] β β β ββ emit AddOwner(index: 0, owner: 0x0000000000000000000000000000000000000000000000000000000000000001) β β β ββ emit AddOwner(index: 1, owner: 0x0000000000000000000000000000000000000000000000000000000000000002) β β β ββ β AlreadyOwner(0x0000000000000000000000000000000000000000000000000000000000000002) β β ββ β AlreadyOwner(0x0000000000000000000000000000000000000000000000000000000000000002) β ββ β AlreadyOwner(0x0000000000000000000000000000000000000000000000000000000000000002) ββ β AlreadyOwner(0x0000000000000000000000000000000000000000000000000000000000000002) Test result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 5.00ms Ran 1 test suite in 5.00ms: 0 tests passed, 1 failed, 0 skipped (1 total tests) Failing tests: Encountered 1 failing test in test/SmartWallet/CoinbaseSmartWalletFactory.t.sol:CoinbaseSmartWalletFactoryTest [FAIL. Reason: AlreadyOwner(0x0000000000000000000000000000000000000000000000000000000000000002)] test_createAccountDeploysToPredeterminedAddress() (gas: 801156) Encountered a total of 1 failing tests, 0 tests succeeded
The vulnerability was identified through manual testing and analysis, utilizing custom test scripts and the Foundry testing framework.
The protocol should consider reverting the create wallet function when the number of owners is 2 or should review this function to ensure that the same addresses will not deploy different account with the same nonce
Error
#0 - c4-pre-sort
2024-03-22T06:01:58Z
raymondfam marked the issue as sufficient quality report
#1 - c4-pre-sort
2024-03-22T06:03:04Z
raymondfam marked the issue as high quality report
#2 - raymondfam
2024-03-22T06:03:29Z
This would indeed be an issue and extend beyond securing SCW deployment on various chains for the same address.
#3 - c4-pre-sort
2024-03-22T06:04:21Z
raymondfam marked the issue as duplicate of #46
#4 - c4-pre-sort
2024-03-22T23:17:30Z
raymondfam marked the issue as not a duplicate
#5 - c4-pre-sort
2024-03-22T23:17:35Z
raymondfam marked the issue as primary issue
#6 - wilsoncusack
2024-03-26T12:41:41Z
This is working as intended. Users need to pass original owners in the same order to get the same address.
#7 - c4-sponsor
2024-03-26T15:01:21Z
wilsoncusack marked the issue as disagree with severity
#8 - c4-sponsor
2024-03-26T15:01:24Z
wilsoncusack (sponsor) acknowledged
#9 - 3docSec
2024-03-27T04:47:18Z
User mistake with no impact other than purely UX - having to recreate the wallet with a different input order.
#10 - c4-judge
2024-03-27T04:47:45Z
3docSec changed the severity to QA (Quality Assurance)
#11 - c4-judge
2024-03-27T04:47:55Z
3docSec marked the issue as grade-a
#12 - c4-judge
2024-03-27T05:40:28Z
This previously downgraded issue has been upgraded by 3docSec
#13 - 3docSec
2024-03-27T05:40:51Z
(temporarily upgrading to to dedupe #114)
#14 - c4-judge
2024-03-27T05:41:42Z
3docSec changed the severity to QA (Quality Assurance)