Unlockd Protocol Update: Testnet Improvements
After a little over a month since we publicly launched the Unlockd Testnet, the results have been surprisingly positive.
We’ve experienced impressive traction, which has helped us to fast-track our troubleshooting process.
Thanks to the constant input from the community (6130 unique users who have left us 2300+ feedback tickets), we have identified a number of issues or improvements to implement that were common to most users.
In an exercise of transparency and following a ‘build in public’ approach, here we tell you what these problems were and how our development team has worked to solve them.
Let’s dive in!
- Borrow APY (interest rate) was displayed by the interface as unreasonably high, with a huge difference with respect to the Lending APY.
- Monthly yield of deposited assets was displayed inaccurately.
- Some healthy loans showed a Liquidation Price higher than the current valuation (with the Health Factor above 1).
- Auctions were terminated 3 minutes after being initiated.
- Users couldn’t bid in some auctions, or it took minutes before being able to access them. Sometimes, when bidding, transactions failed, but bid prices were incremented.
- Approving price valuation for an NFT to be deposited sometimes got stuck forever.
- Available borrowing amounts, when borrowing again in the same loan, sometimes appeared as negative.
- ‘Dashboard’ tab appeared empty.
- Withdrawing max amount from a supplied Earn position raised an error.
- Pop-up prompt confirming a successful withdrawal did not close — user had to close it and refresh the page manually.
- Weird error randomly appeared sometimes: Invalid contract address or ENS name (argument=”addressOrName”, value=undefined, code=INVALID_ARGUMENT, version=contracts/5.6.2)
Issues we are aware of and working on:
- Faucet Error: no NFTs available to mint.
- In a loan, borrowing more or repaying succeeds, but manual page reloading is needed.
- Various typos and tooltip clarity deficiencies.
Detailed explanation of what was broken and how we fixed it
Interest rate appeared unreasonably high
Although the yield offered to lenders was normal, in contrast, the interest charged to borrowers for their loans was exorbitantly high; it did not match the supply-demand proportionality one would expect.
Who on earth would want to borrow on these terms?
This was not a smart contract issue.
The calculations were performed correctly in the back end of the protocol. However, somewhere between the contracts and the interface, there was a coding typo for which a 100% extra cost was shown.
This mismatch has been fixed, and the interest rate is now reasonable—no more fat fingers.
Inaccurate monthly yield
Our mission with Unlockd’s UX/UI is to show relevant and accurate information so that our users can make better decisions.
And here we were not living up to our goal.
The calculation used to show the monthly yield was APY/12 — which is incorrect as it does not take into account the effect of compounding.
Actually, the monthly yield is lower. Again, this is just a front-end error; nothing to do with the contracts. A correct calculation function has been implemented, showing the correct ‘de-compounded’ Monthly yield in the front end.
The math adds up again!
Liq Price > Valuation BUT Health Factor > 1
Ok, this was confusing.
Healthy loans (with a Health Factor > 1) were displaying a Liquidation Price (price at which the loan would be liquidated) below the actual valuation of the NFT (which would imply that the Health Factor should be below 1, thus triggering a liquidation event).
Fortunately, this was again a front-end issue, and liquidation triggers for auctions were working fine.
The flaw: the liquidationPrice variable to be displayed in the UI was calculated with the current LTV — according to what our dynamic risk framework would provide as optimal for the current moment — when the original LTV should be used. This approach, however, involved additional steps as the problem is that we should keep for each loan all LTVs of the partial loans as well as the repayments — a high computation and data storage cost.
So our Data Science team worked on a way of computing the Liquidation Price without using the Loan-To-Value at all.
We define the Health Factor for a loan as:
If we take into account that a loan is going to be liquidated whenever HF ≤ 1, we have:
From where we can isolate the liquidation price (valuationliq) according to:
Renaming the variable for better readability, we have:
Voilà. We now have the liquidation price without using, storing, or even knowing the loan LTV.
The beauty of this calculation is that it allows for a simple UI dynamic display as the user borrows more (or less):
Auctions lasted 3 minutes
Once again, a front-end issue. The auctions ended 3 minutes after they were started (2.82 minutes, to be precise). Not the kind of flash loan you want.
This was because the duration of the auctions was calculated as follows:
Here we have a unit error since the timestamp passed to the front end should be in milliseconds. By multiplying this number by 1000, the error was quickly fixed.
Other smaller issues identified and fixed
Users couldn’t bid in some auctions, or it took minutes before being able to access them. Also, a weird error randomly appeared sometimes: Invalid contract address or ENS name (argument=”addressOrName”, value=undefined, code=INVALID_ARGUMENT, version=contracts/5.6.2), as well as two other errors when using the Auctions module: Unexpected Error and Estimate Gas Error.
Many of these issues were caused by a rate-limit situation with Alchemy. Sorted this out with the wonderful folks there.
Approving price valuation for an NFT to be deposited sometimes got stuck forever. Annoying. This was our bad; we needed to optimize our servers’ queue to enhance the data processing pipeline.
Also, some available-to-borrow amounts, when borrowing again in the same loan, sometimes appeared as negative. This makes sense mathematically, but to avoid user confusion, we decided just to force the display to be 0 in such cases.
Withdrawing the max amount from a supplied Earn position raised an error (e.g., 0.500023 — gives an error, but 0.5 works!). This was caused by a rounding error when interacting with the front end—now fixed. Oh, and the pop-up prompt confirming a successful withdrawal did not close, and the user had to close it and refresh the page manually. This was really annoying and is also now fixed.
We are taking our time to identify and fixall these bugs, and the constant help from our community is proving invaluable.
We believe in the philosophy of doing things right, little by little, and putting the security and integrity of our users’ assets first. We want to build a bullet-proof protocol, no matter how much time and effort it takes us.
After these changes and verifying repeatedly that everything is working as expected, we are getting closer and closer to the mainnet launch.
Closer and closer to a new chapter in Unlockd’s history.
Closer and closer to unlocking the full value of the NFT ecosystem.
See you soon. See you buidling.