WeiDai exploit postmortem

Dear WeiDai community,

It is with deep regret and sadness that I must confirm an exploit has occurred on the WeiDai protocol and that I want to apologize with utmost sincerity to all those affected. My hope for this article is to bring clarity and explain the possible ways of recapitalizing WeiDai in the longer term. Since it’s launch in November 2019, through bull and bear markets, WeiDai has achieved a consistent APY of about 30% without reliance on inflationary incentives, credit or false hype but purely through the tokenomics of burning. The support of so many of you who share the ideal of a thriftcoin — a stablecoin that sustainably beats price inflation and does not require the holder have deep knowledge of finance — has not been lost on me and I won’t rest until WeiDai is back on its original growth trajectory.

The Exploit: ownership

function transferToNewReserve(address reserve) public;

This allows the swapping out of one reserve for another by sending all the Dai to the new reserve. At the time of the exploit, InertReserve’s implementation looked like this:

function transferToNewReserve(address reserve) public {  
uint daiBalance = ERC20(daiAddress).balanceOf(address(this)); require(ERC20(daiAddress).transfer(reserve,daiBalance),
"transferToNewReserve failed at Dai transfer");
}

The exploit occurred because I neglected to add an onlyPrimary modifier to the function. In other words, no check was made on who called the function. This is the one of the most trivial bugs and it was certainly not committed intentionally. The person who exploited this bug simply had to execute the function and supply their own address. This is the transaction for the withdrawal of the 50,146.78 Dai.

https://etherscan.io/tx/0xb2608a53f8291789a3dd2b73a68576f000a8c29e337b7eab74e1df7ce0498206

While exploiting this required some thorough investigation, the fault lies with me and I take full responsibility for the loss of funds and do not hold the exploiter accountable. If the person who executed this transaction is reading this and is willing to return any portion of the funds, I will be prepared to make a long term commitment to reimburse the full amount with interest and will maintain complete anonymity and indeed gratitude for performing such a strong white hat test on the protocol before even more funds were put at risk.

Immediate Actions taken

The WeiDai front end has been paused until further notice.

The bank contract exposes a function called daiPerMyriadWeidai which, as the name suggests, returns the quantity of dai in reserve for every 10000 WeiDai. This initial value for this number was 100, implying a starting redeem rate of 0.01. At the time of the exploit, the ratio was sitting at 166, implying that the redeem rate had grown by 66% since launch. Given the reserve of about 50000 Dai, this implied a circulating supply of WeiDai of just over 3 million. After the exploit, the new daiPerMyriadWeiDai would be about 19x10000/3000000 = 0.063333333. However Ethereum does not have fractional units which means it would be 0. Minting WeiDai involved a division by this number so for now, minting will fail. However, as soon as the Dai in reserve exceeds 300, the number will be 1, at which point minting and redeeming can resume.

Since WeiDai trading on Behodler is suddenly overvalued, being able to mint WeiDai cheaply would constitute a way to withdraw liquidity. For this reason, trading of WeiDai on Behodler has been halted and minting of WeiDai has temporarily been halted.

Possibilities for recapitalisation

  1. Me: As funds make themselves available, I will personally replenish the reserve.
  2. Yield: As mentioned earlier, the intent of the reserve is to put the Dai to work in DeFi. One reason I was holding back was to utilize a post-Limbo Behodler in order to swap out Dai for something that generates high ongoing yield denominated in stablecoins such as OUSD or a PyroToken for a Yearn stablecoin LP token. This would automatically edge WeiDai growth into a position of being, by definition, the best stablecoin instrument in DeFi. This would be in addition to the approximately 30% growth that has occurred purely from burn tokenomics.
  3. Limbo: Limbo has a surprising degree of flexibility and one of the uses put forward in the community is to use it to recapitalise a bonding curve. For instance, Limbo offers a pool with a decent APY on WeiDai and a threshold for migration. At the point of migration, in addition to burning SCX, burn WeiDai. If calibrated correctly, this could mutually benefit WeiDai, Flan and SCX while instantly transferring value back to WeiDai holders.
  4. External funding for WeiDai: WeiDai started as a passion project and has to date not received a cent of external funding, nor has a cent been spent on marketing, all the while achieving 30% consistent APY. In that time, the cryptocurrency markets have matured and WeiDai would benefit tremendously from a refreshed UI, deep liquidity reserves on multiple AMM in order to encourage arbitrage burning, and perhaps a more concerted marketing push.

Option 3 requires testing and investigation to ensure that it is purely for the mutual benefit of all communities in involved but most of all it requires a completion to a fully tested Limbo. Part of the reason for the delay in Limbo has been because I have been applying a formal verification technique for smart contracts in addition to the usual testing procedures. I have no doubt that it would have caught this exploit had I applied it to WeiDai.

Closing thoughts

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store