Skip to content

joshpwrk/base-ethdenver-bounty

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Solution to Base ETHDenver Bounty Challenge

Got dragged into the Base's 2023 challenge while perusing twitter on a Saturday afternoon. Figured I clean up the solution and post publicly for anyone who's curious how it was solved.

TLDR: Signatures can be 64bits or 65bits long. If you have a quirky implementation of ECDSA.sol (like Base did on purpose) you can end up with two different signatures that result in the same signer.

Challenge description: https://www.coinbase.com/bounty/ethdenver23

Solution Overview

Challenges 1 & 2 were quite straight-forward and do not need any explanation apart from the actual code in Solution.s.sol.

The third challenge, however, was a tough nut to crack. Here's the logical steps that led me to finding the solution (honestly about ~2hrs):

  1. Realize that the only way to pass is to submit two different signatures that result in the same signer
  2. Actual ECDSA collisions are not practical - we'd have bigger issues if they were
  3. Considered maybe abi.encodePacked created some weird inconsistencies, but Riddle.sol L136 specifically checked post packed results so that wasn't it
  4. Finally, I figured I'd take a look at how the ecrecover was done
  5. If there are any weird tricks, they will show in the diff between OpenZepellin's ECDSA.sol contract.
  6. Boom boom -> Base challenge added another branch where signature can either be 64 or 65 bytes long.
  7. From here on it was pretty quick to realize that packing v into s would result in a different signature
  8. There were a couple hurdles you'd need to jump through if you're not familiar signature signing -> e.g. ECSDA.sol assumes v is 0 or 1 and then adds 27.

Installation and Build

git submodule update --init --recursive
forge build

Running on-chain

Create a local .env file with the below vars:

PRIVATE_KEY=
PUBLIC_ADDRESS=
BASE_GOERLI_RPC_URL='https://goerli.base.org'

Then run the Solution.s.sol script to complete all three challenges in one go:

source .env
forge script script/Solution.s.sol:Solution --rpc-url $BASE_GOERLI_RPC_URL --broadcast --verify -vvvv

About

Solution to Coinbase Bounty Challenge (ETHDenver 23)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages