Note: This repo is out-dated. I now work on LibSubmarine, a smart contract library making it easy to use Submarine Sends in your contract.
This repo contains a proof-of-concept implementation of Submarine Sends for Ethereum as described in the blog post "To Sink Frontrunners, Send in the Submarines" by Lorenz Breidenbach, Phil Daian, Ari Juels, and Florian Tramèr.
This is a proof-of-concept implementation written for research purposes. The code has not been audited and may contain bugs or security vulnerabilities.
In particular, the code does currently not support Merkle-Patricia-proofs; a potential adversary could frontrun reveals until these are implemented.
To run the tests in this repo, you will need
- a recent version of the Solidity compiler
solc
: Consult the solidity docs for installation instructions. python
>= 3.6 (for pyethereum) andpip
If you want to assemble the EVM assembly files, you will also need the evm
tool which is a part of go-ethereum.
You should then be able to install any dependencies by running
pip3 install -r requirements.txt
The contract/
directory contains three contracts:
auction.sol
is an example of a simple sealed-bid auction contract that makes use of Submarine Sends. Here is how it works:- The auction starts when the contract is created. Participants have
COMMIT_WINDOW
blocks to place a bid. - To place a bid, a participant calls
commitAddress
passing in the desiredbid
amount (in Wei) and a randomly chosen 256-bitwitness
and sendsbid
Wei to the returned address. - Once
COMMIT_WINDOW
blocks have passed since the creation of the auction contract, a participant should reveal her bid by callingrevealBid
with the samebid
andwitness
passed tocommitAddress
. Unrevealed bids remain locked up forever! - Once
REVEAL_WINDOW
blocks have passed since the end of the commit window, no more reveals are accepted. Participants can usehighestBidder
to check whether they won the auction. The highest bidder should callfinalizeWinner
to be officially acknowledged as thewinner
of the auction. Everybody else should callfinalizeLoser
to receive a refund for their bids. finalizeWinner
andfinalizeLoser
have a high gas cost because they need to create many contracts. To successfully call them, you need to pass in at leastFINALIZE_MIN_GAS
gas (this is to ensure progress). Since finalization may cost too much gas to fit into a single block, you may have to repeatedly callfinalize*
until it returnstrue
to indicate that it is done.
- The auction starts when the contract is created. Participants have
forwarder.easm
contains EVM assembly code for a forwarder contract that allows its owner to withdraw funds and anybody to create further clones of the contract.initcode_header.easm
contains EVM assembly initcode that can be prepended to any contracts code (assuming that the contract doesn't need storage initialization).
test/
is for tests:
test_auction.py
contains the test-suite forauction.sol
.
The auction.sol
contract has a test-suite. You can run it like this:
python3.6 -m test.test_auction
To assemble/compile foo.easm
, simply run
evm compile foo.easm