Gloom

How decentralized is DeFi? If you look at the ownership of governance tokens, the answer is "not very." With few exceptions, a handful of addresses hold majority stakes in most DeFi projects.
Let's say you're a founder or investor in a top project like Compound, Maker, Synthetix, Aave or Chainlink and you'd like to sell a large stake. The market caps for the tokens of these projects is in the billions, so even a 5% stake is worth hundreds of millions of USD.
How could you go about selling your tokens? There wouldn't be enough order book liquidity on a centralized exchange like Binance, nor enough pair liquidity on a decentralized AMM like Uniswap.
Large transaction today are typically negotiated off-chain through personal relationships, or in a centralized way through market makers. I think there's a better, decentralized way: a private auction – akin to an M&A sales process in traditional finance – conducted on the Ethereum blockchain.
This idea is the inspiration for Gloom, a platform I built at the ConsenSys Blockchain Developer bootcamp which enables a seller to hold an invite-only auction of ERC-20 tokens. Using Gloom, a seller invites bidders (contacts and/or "whales") to bid on the tokens, with the seller and winning bidder exchanging tokens and payment (in ETH) through an escrow contract.
Auction process
- Setup: seller configures the type and amount of tokens, makes an ETH deposit into the auction contract, invites bidders (Ethereum addresses) and sets a bidder ETH deposit requirement.
- Commit: bidders deposit into the auction contract and present their bids (in ETH) for the tokens. Bids are hidden (salted and hashed) and recorded on the blockchain.
- Reveal: bidders reveal their bids (only if they match the earlier commits), with the winner determined and an escrow contract deployed.
- Deliver: seller and winning bidder deliver tokens and payment, respectively, to the escrow contract.
- Withdraw: seller and winning bidder withdraw proceeds and tokens, respectively, from the escrow contract. Everyone withdraws their deposits from the auction contract.
Links
- GitHub (mono repo with a React project and Truffle project with Solidity smart contracts)
- Video demo walkthrough (12 minutes)
Minimal-proxy
As the first step in conducting an auction, the seller configures the type and amount of ERC-20 tokens they wish to sell. On submit, the React frontend (using ethers.js) calls a function on the auction factory which deploys a new auction using a minimal-proxy pattern, implemented using Open Zeppelin's ProxyFactory contract.
Minimal proxies are a way to clone contracts in order to save on transaction gas fees. When I first implemented the factory using a traditional, non-proxy pattern, creating an auction required more than 1 million gwei of gas vs. a little over 200k currently. Essentially, the minimal proxy reuses the bytecode of a pre-deployed "logic" contract using delegate calls, a pattern standardized in EIP-1167.
Escrow delivery
When the seller triggers the deliver phase, the auction contract declares the winner and deploys a new escrow contract. The seller and bidder then deposit their tokens and payment (in ETH), respectively, into the contract, with checks to ensure both have deposited before allowing withdrawals.
Tests
I wrote unit tests for the Solidity smart contracts in JavaScript using Truffle's test framework, which builds on top of Mocha and uses Chai for assertions. I added the Truffle Assertions package for testing expected revert conditions (e.g. unauthorized message sender).
Web3-react
On the React frontend, Gloom uses the web3-react package by Uniswap's Noah Zinsmeister to connect with the web3 provider that is injected into the browser (e.g. by MetaMask), putting it into a Context.
Design
As the saying goes, "good artists copy, great artists steal." Gloom's neumorphism "soft UI" design is based on code I forked from Marta Mullor and CodingNepal.