The NFT contracts and staking index behind Bipzy's token launch
Bipzy raised 80 ETH on launch day. We led the smart-contract work behind its launch: we wrote the Bipzy NFT collection and the BipzyPass access pass, fixed the presale pool, added to the staking contract and indexed every stake.
- Client
- Bipzy
- Service
- Blockchain
- When
- December 2023 to November 2024
- Team
- Mihir, Angel Lakra
- Status
- Live
- Public proof
The problem
Bipzy was preparing a token launch that rewarded its community. Holders of an earlier NFT collection were to carry over into a new Bipzy collection. A second NFT, BipzyPass, gave access. Holders could stake either NFT for a fixed period. A stake gave them a boost: a higher limit on how much they could put into the presale pool. The presale pool is where other projects raise on Bipzy's platform.
The launch was a set of contracts on Ethereum: the collection, the pass, the staking contract and the presale pool. Each contract held holders' NFTs or their ETH. A pricing bug in a mint, or a stake recorded wrong, would cost holders or Bipzy money in public, on launch day.
What we built
We wrote the Bipzy collection. A holder of the earlier collection deposits that NFT into the new contract and receives a Bipzy NFT in its place. Others mint at a price set by Bipzy, with a discount for eligible holders. The art is revealed after the mint. We built the collection on ERC721A, which keeps the gas cost of minting several NFTs at once close to minting one.
We wrote BipzyPass, which Bipzy releases in batches, with a share reserved for Bipzy holders. The contract keeps one Merkle root instead of storing every eligible holder on chain. Each holder proves their place in the list when they mint. The Merkle root keeps the mint cheap. The list is a snapshot, so a new holder qualifies only when Bipzy publishes a new root with the next batch.
The presale pool came to us already written. An audit of the pool returned findings. We fixed them, from checks at setup to an interface mismatch. On the staking contract, we added the check for rare Bipzy NFTs and an owner action to force an unstake. We also added a fix so a new stake never overwrites an existing one.
We also wrote the subgraph that indexes every stake. With the subgraph, the app can show a holder's stakes. The presale pool can check a holder's boost against a Merkle root built from that index.
Angel Lakra, on our Team, worked on the web app. Angel connected the web app's presale, booster, staking and claim screens to the contracts.
What was hard
The holder discount priced the mint wrong twice. The first version of the discounted mint divided by the discount instead of multiplying. That version would have charged holders more than the full price. The second version charged them the discount amount itself rather than the price after the discount. We fixed both in testing, before any deployment.
Then we checked whether the tests would have caught bugs like these on their own. We ran Gambit mutation testing on the NFT contracts, and later set it up for the staking contract. Gambit changes the contract code in small ways and reruns the tests. A change that the tests miss shows a gap in the tests. The Bipzy collection's tests run against a fork of Ethereum mainnet, so we test the deposit flow against the real earlier collection.
The result
Bipzy raised 80 ETH on launch day through the Bipzy NFT contract we wrote. The staking contract is deployed on Ethereum. Its source is verified on Etherscan.
Built with
| Contracts | Solidity, with OpenZeppelin upgradeable contracts |
|---|---|
| NFTs | ERC721A, with ERC-2981 royalties |
| Holder allowlists | Merkle proofs |
| Tests | Foundry, with Ethereum mainnet fork tests |
| Mutation testing | Gambit |
| Deployment | Hardhat, on Ethereum |
| Staking index | The Graph subgraph |
| Web app | Next.js, wagmi and viem |