- Total Prize Pool: $40,000
- HM Awards: $37,000
- LQAG Awards: $3,000
- Starts July 24, 2023
- Ends August 5th, 2023
- nSLOC: ~182
- Complexity Score: ~106
Actors
- Buyer: The purchaser of services, in this scenario, a project purchasing an audit.
- Seller: The seller of services, in this scenario, an auditor willing to audit a project.
- Arbiter: An impartial, trusted actor who can resolve disputes between the Buyer and Seller. Design considerations
- The Arbiter is only compensated the
arbiterFee
amount if a dispute occurs. - Once a dispute has been initiated it can not be canceled.
- ERC777 tokens should not be used as tokens for the
Escrow
contract given that it enables a malicious buyer to DOSEscrow::resolveDispute
- In case a smart contract calls
EscrowFactory::newEscrow
, given that the caller of this contract is in control of the salt, frontrunning is a possibility.
Create an Escrow
- Buyer approves the payment contract to be handled by
EscrowFactory
. - Buyer calls
EscrowFactory::newEscrow
, inputs:- The price.
- The payment token.
- The seller (auditor or person in charge of the audit).
- Arbiter.
- Arbiter fee: Fee to pay in case of a dispute is initialized.
- Salt: for
create2
Escrow
deployment.
Expected sucessful workflow
- The buyer creates an
Escrow
contract throughEscrowFactory::newEscrow
, depositing the funds. - The seller sends the buyer the report (off-chain).
- The buyer acknowledges this report on-chain by calling
Escrow::confirmReceipt
. This sends the funds to the seller.
Expected dispute workflow
- The buyer creates an
Escrow
contract throughEscrowFactory::newEscrow
, depositing the funds. - For any reason, the buyer or the seller can initiate a dispute through
Escrow::initiateDispute
. - The arbiter confers with both parties offchain. Arbiter then calls
Escrow::resolveDispute
, reimbursing either side accordingly, emptying theEscrow
.
- Submit to CodeHawks
All contracts in src
are in scope.
Note on script
folder:
The contracts in script
are the scripts you can assume are going to be used to deploy and interact with the contracts. If they have an issue that will affect the overall security of the system, they are in scope. However, if they have a security issue that only affects the script and not the overall deployment of the stablecoin protocol, it is out of scope.
- Addresses other than the zero address (for example 0xdead) could prevent disputes from being resolved - Before the
buyer
deploys a newEscrow
, thebuyer
andseller
should agree to the terms for theEscrow
. If thebuyer
accidentally or maliciously deploys anEscrow
with incorrectarbiter
details, then theseller
could refuse to provide their services. Given that thebuyer
is the actor deploying the newEscrow
and locking the funds, it's in their best interest to deploy this correctly. - Large arbiter fee results in little/no
seller
payment - In this scenario, theseller
can decide to not perform the audit. If this is the case, the only way thebuyer
can receive any of their funds back is by initiating the dispute process, in which thebuyer
loses a large portion of their deposited funds to thearbiter
. Therefore, thebuyer
is disincentivized to deploy a newEscrow
in such a way. - Tokens with callbacks allow malicious sellers to DOS dispute resolutions - Each supported token will be vetted to be supported. ERC777 should be discouraged.
buyer
never callsconfirmReceipt
- The terms of theEscrow
are agreed upon by thebuyer
andseller
before deploying it. The onus is on theseller
to perform due diligence on thebuyer
and their off-chain identity/reputation before deciding to supply thebuyer
with their services.salt
input when creating anEscrow
can be front-runarbiter
is a trusted role- User error such as
buyer
callingconfirmReceipt
too soon - Non-
tokenAddress
funds locked
This project is meant to enable smart contract auditors (sellers) and smart contract protocols looking for audits (buyers) to connect using a credibly neutral option, with optional arbitration.
- CodeHawks Escrow Contract - Competition Details
- About
- Getting Started
- Usage
- Deployment to a testnet or mainnet
- Formatting
- Acknowledgements
- git
- You'll know you did it right if you can run
git --version
and you see a response likegit version x.x.x
- You'll know you did it right if you can run
- foundry
- You'll know you did it right if you can run
forge --version
and you see a response likeforge 0.2.0 (816e00b 2023-03-16T00:05:26.396218Z)
- You'll know you did it right if you can run
git clone https://github.com/Cyfrin/2023-07-escrow
cd escrow
forge build
forge test
forge coverage
and for coverage based testing:
forge coverage --report debug
make anvil
This will default to your local node. You need to have it running in another terminal in order for it to deploy.
make deploy
- Setup environment variables
You'll want to set your SEPOLIA_RPC_URL
and PRIVATE_KEY
as environment variables. You can add them to a .env
file, similar to what you see in .env.example
.
PRIVATE_KEY
: The private key of your account (like from metamask). NOTE: FOR DEVELOPMENT, PLEASE USE A KEY THAT DOESN'T HAVE ANY REAL FUNDS ASSOCIATED WITH IT.- You can learn how to export it here.
SEPOLIA_RPC_URL
: This is url of the goerli testnet node you're working with. You can get setup with one for free from Alchemy
Optionally, add your ETHERSCAN_API_KEY
if you want to verify your contract on Etherscan.
- Get testnet ETH
Head over to faucets.chain.link and get some tesnet ETH. You should see the ETH show up in your metamask.
- Deploy
make deploy ARGS="--network sepolia"
You can estimate how much gas things cost by running:
forge snapshot
And you'll see and output file called .gas-snapshot
To run code formatting:
forge fmt
- Inspiration for the codebase from Ross Campbell