Apologize for the long wait, here it is:
This is probably the hardest document I’ve ever had to write. For those out of the loop, http://dripp.farm had its liquidity pools drained for both the ALVIN and SHWEATPANTS tokens. After the “dripp-ocalypse” of last week, this is a retrospective on the Dripp product and how it came into fruition. This document is meant to be primarily technical. No parties involved (except myself) will be named or called out. I’d like to avoid a he said-she said situation.
My personal apology is at the end, if you’d like to skip to that.
Dripp Development Timeline
Pre-Dripp
On Nov 04, 2020 Shenanigan announced the Shweatpants idea. Originally planned to be a swag drop to the Shenanigan community to incentivize liquidity, PRTCLE and LP holders would stake tokens to earn points to be redeemed for an NFT and a real pair of sweatpants. In our weekly blogpost series we reference it here SHWEATPANTS | Weekly Newsletter #7 - Shenanigan’s Newsletter.
I decided to use the audited Aavegotchi ghost staking diamond contracts to generate the points system for the NFTs. Around Nov 14, I had finished forking the contracts and began testing on rinkeby testnet. I had also begun work on a simple staking frontend similar to aavegotchi frontend
We were days away from launch when I made this proposal on the 1hive forums
Introducing HNY socks
Since xDai has always been a community about collaboration. It seemed appropriate to give the rest of the community the “opportunity” to be a part, with Shenanigan taking a primary role in development and production. Like many others in the community, we were not happy with the state of liquidity on honeyswap/xdai and this was Shenanigan’s move to help fix it. Reminder, this was when liquidity was at its lowest at around $3million on honeyswap
Dripp
After a couple months, I wrote the second blogpost. After a bit of back and forth with Buzzdao, 1hive’s marketing swarm, we had decided to move forward with a different piece of swag than socks and go by the name “Dripp”. The community decided to make a dripp shirt and deliver 50% of the NFTs via staking and 50% to be delivered via purchase. This was a notable change from Shenanigan’s original plan of allocating 100% of the NFTs to staking.
Note, at this time, we had still not decided to do a direct fork of unisocks, and were still using the points idea
I then wrote this proposal/blogpost
About 2 weeks later, the Shenanigan and 1hive teams had a meeting and decided to go with a direct unisocks fork. Unisocks was an ERC20 token that can be redeemed in whole number quantitites for an NFT and a real pair of socks. I started development on Dripp that day.
On February 16 the first commit was made for Dripp Staking Contracts, which also used the ghst staking contracts as a base template.
This was a major design decision. The critical reason being ghost staking contracts are non-deterministic, meaning points accrue to infinity, instead of a deterministic model that accrue proportionally to a total.
While the end result of the two, is very similair, there is one key difference between them. Using a non-deterministic model allows for points to overlap, after the staking period has ended. Therefore, unclaimed rewards could be reclaimed by those who were attentive to the project. I made this decision as an attempt to create a fun feature for those who believed in the project to be rewarded further. I will talk more about this in the section after Dripp launch
Unisocks Fork
Forking any project always comes with its own hurdles. This specific fork presented a few major pain points
-
Contracts written in vyper
Unisocks and Unisocks NFTs were both written in vyper, a python smart contract programming language. I am not familiar with vyper and therefore I recreated the contracts using OpenZeppelin token contracts code to my best ability. -
Adjusting the frontend to handle two tokens.
Unisocks frontend was built for one token, which contained its own limitations. Much of the main logic in the app had to be reorganized and rewritten to accomodate for two tokens. Anything that involved state had to be rewritten as it used a single variable instead of a data structure to store data. -
Rewriting the frontend for Uniswap v2
Unisocks frontend was built for Uniswap v1. More of the logic in the frontend had to be changed to use Uniswap v2, Honeyswap’s implementation. I had never worked with Uniswap before so this took its own research and solution -
Dripp Staking
Of course, there was the entire staking UI. I will talk about this further along in the post.
DrippStaking Outline
Here is an outline of the DrippStaking contracts:
function startDripp(
address token,
address primaryToken,
address lpToken,
uint256 activeTime,
uint256 supply
) public onlyOwner {}
- Sets staking paramaters for dripps. This function was only used in the constructor on launch to start staking rewards
function reward(address _account, address token)
public
view
returns (uint256 reward_)
- A view only function that would read the state of the staked account and calculate rewards accrued since the last rewards were calculated
function updateRewards() internal {}
- Called each time tokens were staked, claimed, or withdrawn and each time rewards were calculated
function claim(address token) external {}
- Used to claim the tokens. Used return of the reward function.
Dripp Staking UI
Alongside the contract work, the staking needed a UI to go with it. Staking was novel to dripp and a key component to the platform. It was of the utmost importance to get right. This meant giving end users a clear picture of what was going on, or the best I could do. Writing the logic to connect the contracts to the frontend, involves allowing for staking, withdrawal and claiming.
I also added a daily accrual amount at the top. APY was in the works, but was left on the wayside with other issues taking priority.
On February 21, I wrote the proposal for providing HNY to buzzdao for the ALVIN liquidity
And by March 02, the tokens launched with the original ALVIN v1 code,
The story of Alvin
The original Alvin V1 contained no minting function. It was a fork of the base level OpenZeppelin ERC20 Token Contract.
Thus it was capped at 100 ALVIN after launch. 50 Alvin were delivered to buzzdao, and 50 were given to the staking contracts. Starting at a price of 35 XDAI, Alvin quickly rose to a price of > $3500. As expected, this genereated a lot of hype and excitement for staking.
The plan was to launch staking the day after on https://dripp.farm.
So a day later, as planned, staking launched.
Unfortunately, rewards were not accruing for LP holders. Caused by an oversight during my tests on remix testnet where using the same token address for both staking types (single token and LP) resulted in correct rewards.
Thus Buzzdao and Shenanigan had to make a decision.
-
Leave the contracts as they stand with no LP incentive
-
Nuke rewards for that day, and relaunch the contracts with a new token
Since dripp was originally about liquidity, the decision was made to relaunch. So, I worked for the next 2 days rewriting the contracts for the update. This entailed fixing the bug of the previous contract, and using previous staked tokens in rewards calculation. The second was extremely important so users wouldn’t need to migrate their stake to receive rewards. A good majority of this work was done live in the 1hive discord.
I also rewrote the ALVIN token contracts to use OpenZeppelin’s ERC20PresetMinterPauser
token contracts. This was made to give more control over the tokens post launch, such as adding MINTER
and BURNER
roles, as well as being able to pause the token, if any other problems were to arise. I was given the MINTER role here. Most of this coding was done live in the 1hive #cafe chat, in case any 1hivers were to stop by and give assistance. I appreciate sandpiper and luigy lemon for giving their 2 cents on these issues.
Thus ALVIN V2 launched,
Unfortunately, the DrippStaking contract was launched with incorrect parameters. And thus V2 was scrapped for V3.
It’s worth noting that there was no need to scrap V2, other than for the purpose of keeping the total token supply at 100. Since the ALVIN tokens were locked away in the incorrect parameter contract, it was just as viable to mint more for the Staking contract with the right params. This was an oversight on my part.
Thus, Alvin V3 launched, with a new staking contract that pulled from the past staking contract.
Staking Contract: DrippStaking/DrippStaking.sol at 5ebd4187721c7bb8fed78a409ba78d00918b52a5 · ShenaniganDApp/DrippStaking · GitHub
This staking contract contained a migration bug, however, another oversight on my part.
Here’s what happened. The DrippStaking (and GhstStaking) contracts were not made to have initial values set before staking began. So, when old staking numbers were used to initialize the contract, anyone who had stake in the old contracts had their rewards calculated from block 0, instead of the contract launch time. This caused a massive leak of ~22 ALVIN and ~8 SHWEATPANTS.
Luckily, due to using the new openzeppelin contracts and having ownership, I was able to pause ALVIN trading till I could fix the issue, mitigating more being lost.
I promptly patched the bug and launched a new staking contract, using a snapshot of the old token numbers before the bug.
After all that work, Dripp stabilized and everything seemed fine. The plan moving forward was to work on the burning mechanism, make the NFTs, and order the plushies. After a hard launch, some stability was welcome.
Stable Dripp
As staking was coming to a close, Shenanigan made sure to announce that dripp users needed to claim their farms as the overlap of points was meant to occur around April 4th. Shenanigan encouraged 1hive to make announcments as well.
I then purchased the plushies from www.stuffedanimalpros.com. The site only allowed increments of 50, so an order of 150 were made. I was then asked to make another proposal to pay for these after I ordered them. My 4th proposal in this process.
Dripp-ocalypse
On May 25th, I woke up to a message from D0SH asking me to check ALVIN contracts
Once I looked, I realized immediately the minting role had been compromised, as well as my primary account, vginelli.eth. I immediately took action and was in contact with 1hive through discord, however it was too late. The attacker(s) minted 1000s of ALVINs and SHWEATPANTS and used those to drain the liquidity pools, at the time worth about $20k between the two tokens. However, the damage had been done and ALVIN and SHWEATPANTS were again vanquished.
Here is the commit that leaked my PK: Status and result enums by youngkidwarrior · Pull Request #239 · ShenaniganDApp/shenanigan-monorepo · GitHub
What’s Next
I have plenty of things I would have done different in hindsight, some things could have been avoided with an extra week of dev review.
But I will leave the dripp V2 for another post.
The action plan I put together included a few things:
- Snapshot both tokens state prior to the leak
- Snapshot Liquidity tokens prior to leak
- Hire a Raid Guild member to help write, review, and deploy code.
- Send already ordered ALVINs and SHWEATPANTS to legacy token holders.
- Snapshot ALVIN and SHWEATPANTS holders for Dripp V2 launch.
It’s official that the Agave team is going to pull ALVIN outside of Dripp and handle everything themselves. So Shenanigan will not be covering a Raid Guild dev. I’m sure some Agave members can help answer in the comments.
As for liquidity, we are currently working a solution. In the grand scheme, $20k is not the end of the world. Most of the damage is in name alone. Liquidity will be added back to the tokens via 1hive and Shenanigan, and Shenanigan will refund 1hive over time (details of the refund have not been worked out).
**The tokens should in theory should revert to their past state before the hack! **
I am not allowed to send out early ALVINs, however legacy SHWEATPANTS sweatpants will be sent out. If you owned $SHWEATPANTS, make sure to go to the Shenanigan Discord for updates.
Personal Reflection and Apology
All I can start with is sorry. Sorry to the 1hive and Shenanigan communities. Sorry to the token holders. Sorry to those that supported this project. The few who I have spoken with were not just collegaues, but good friends and I failed them. With failure, comes responsibility. I will take responsibility for what happened at launch, and what happened 10 days ago. It’s inexcusable and frankly embarrasing.
With the words I’ve written here, I hope I painted a clear picture of the passion I hold, not just for Shenanigan, but for 1hive as well. It’s been a long 8 month journey building Dripp and it hurts to see this chapter close so harshly. To those who are looking for redemption, Agave and Shenanigan are doing work to revitalize the tokens and refund the money lost.
As for my personal relationship with 1hive, I think I’ve made it clear I am apologetic, however, it’s not excusing me from my action. I will still be around the community, however taking a much less eventful role for the forseeable future. It is never easy to regain trust, once it has been lost.
The one thing I ask is please come talk to me if you have things to say, and leave the hateful rhetoric out of discords, telegrams, and forums. The communities of web3 like 1hive are made to create value, not spread ill will.
Hope all of your days go well,
Victor (YoungKidWarrior)