Closed c4-bot-4 closed 6 months ago
raymondfam marked the issue as primary issue
raymondfam marked the issue as sufficient quality report
Could have had a coded POC. Seems infeasible with SCW proxy and backend controlled but will let the sponsor review.
Right, is something we discussed but we forgot clean up @xenoliss. Agree this can lead to loss of funds, if calling directly and not using ERC-4337. We should probably just make this function not payable.
Bob the front-runner gets his account contract created.
This is not really correct. Bob just deployed Alice's account, which presumably has owners only she controls.
Could have had a coded POC. Seems infeasible with SCW proxy and backend controlled but will let the sponsor review.
There's no way to exploit this with how we use it--because we use ERC-4337 and users can't send ETH on this create call--but it is still legitimate, in abstract.
wilsoncusack (sponsor) confirmed
The finding is technically invalid. When the clone is not created, LibClone.createDeterministicERC1967
backs up by sending the value that would have been sent at creation:
File: LibClone.sol
850: if iszero(extcodesize(instance)) {
851: @> instance := create2(value, 0x21, 0x5f, salt)
852: if iszero(instance) {
853: mstore(0x00, 0x30116425) // `DeploymentFailed()`.
854: revert(0x1c, 0x04)
855: }
856: break
857: }
858: alreadyDeployed := 1
859: if iszero(value) { break }
860: @> if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
861: mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
862: revert(0x1c, 0x04)
863: }
864: break
So if no value is lost, in the proposed exploit scenario, there is no damage to Alice, because Bob's frontrun created the wallet for her. The wallet that Bob created for Alice is identical to what Alice would have created (Alice is the owner, and it's not compromised in any way), so it appears to be safe and the only visible effect of the attack is that Bob offered Alice the gas required to create her wallet.
3docSec marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2024-03-coinbase/blob/main/src/SmartWallet/CoinbaseSmartWalletFactory.sol#L38-L56
Vulnerability details
Impact
Root cause
create2
deterministic deployment to cause DOS.createAccount(...)
is payable and does not revert when deterministic deployment fails, the ETh sent withcreateAccount
can be lost and stuck in the contract whencreate2
is front-ran.Note that the revert in
LibClone.createDeterministicERC1967(...)
is not bubbled up so the need to check the returnedalreadyCreated
andrevert
is necessary.Proof of Concept
The
LibClone.createDeterministicERC1967(...)
function used in thecreateAccount(...)
function usescreate2(...)
to deterministically deploy a contract. Thecreate2(...)
deterministic deployment can be frontrun by anyone to cause denial of service.The
createAccount(...)
function ispayable
and allows users to create and send ETher to the created account in the same transaction.When a user calls the
createAccount(...)
function and an attacker frontruns that transaction to create a contract at the same address, thealreadyCreated
returned variable istrue
. This is due to the fact thatcreate2
used in theLibClone.createDeterministicERC1967
function creates a deterministic address which anyone can frontrun to take up the address.The main issue is the the transaction that calls the
createAccount(...)
function does not revert whenalreadyCreated
returned variable istrue
. This will cause the ETher sent along with the transaction to be stuck in the CoinbaseSmartWallet contract forever.The
createDeterministicERC1967
functionExploit Scenario
createAccount(...)
function with 1 ETHcreateAccount(...)
Bob can setup bots to monitor the mempool for this type of exploit. This would cause users to lose ETH and also unable to create Account.
Tools Used
create2
Recommended Mitigation Steps
alreadyCreated
is false like below. But this can still be DOSed by frontrunning but will not lose ETH so its better to go with the second recommendation below this code.create
instead ofcreate2
like theLibClone.deployERC1967(...)
function. This is becausecreate2
can be DOSed through front-running butcreate
cannot be DOSed.Assessed type
DoS