Closed sparrowDom closed 4 years ago
This seems like the sort of thing that can depend on a centralized service. Its purpose is purely for user experience and not for on-chain logic, so I would think we would want to avoid adding more on-chain storage. I'm not sure what all @tomlinton has planned for his APY solution, but maybe we take that opportunity to store rebase events, take APY snapshots, and smooth it all out and give the DApp a small growth factor to apply to balances.
The fundamental problem is rebases don't happen often enough yet. The animated balance will always reset if a user goes away and comes back because we are currently rebasing once a day (if that). So I don't think increasing the accuracy of the animated value (or the APY) will solve this.
I think we should revisit this when we've got a) more usage, b) more rebases and c) higher yield/more accurate yield calculation.
@micahalcorn mentioned another user had this issue.
Discussion from Discord: @sparrowDom : Suggesting that for a quick fix, we could pick up the animation of OUSD from when we left it. And if significant time passes in between we just simulate the mean time increase. We would store the necessary stuff into local storage, so it wouldn't work across devices.
@micahalcorn : I think that makes sense as long as we can tell if there has been a consequential event since the balance was las retrieved. It could be a rebase, mint, redeem, or transfer
@sparrowDom : It would be a bit harder getting the consequential events. Was thinking of a simple as possible solution that should cover 90% of the cases. We just check the balance the OUSD contract returns. If it is the same when we were animating it last time we assume no consequential event happened. If it is not the same event like that happened.
One thing we would wrongly assume here is when user sends OUSD or receives OUSD. We would consider that as a consequential event when it isn't. But I would be happy with this as an initial low effort solution.
Wouldn't it affect the balance though? Or I guess you would just track the "estimated earnings" (as opposed to estimated balance) and add that to whatever the on-chain balance is, assuming no rebase since the last timestamp?
I think both mentioned methods of tracking would get us to the same results.
Once we are able to detect coin transfers and rebases (and times of those events) the math would slightly complicate. Since the base we multiply APY with to get earnings from can change. So for example to get earnings from the following events ordered by time:
To get the estimated earnings on t4
time we should calculate: (t3-t2) * OUSDBalance2 * Apy + (t4-t3) * OUSDBalance3 * Apy
. So for each time interval we pick the OUSDBalance value at that time. And even this formula has its flaws, since it ignores the volatility of the APY.
So "what is my current balance" is actually the number one, most common, user interaction by someone who has OUSD.
This is super critical interaction because its how users judge the trustworthiness, performance, and fun of OUSD.
Users rightfully freak out when the number goes down on them - OUSD is losing their money. They also rightfully freak out when their mobile DAPP balance is off (by a quarter of a cent) from the balance shown on their desktop dapp. Clearly something is broken and neither number is trustworthy.
We are fixing the random ups and downs with the rebase changes today.
This leaves displaying their balance in a way that is roughly consistent across browsers.
We might want to make a distinction between the actual balance that you can spend / transfer, and unrealized/unrebased yield that is constantly climbing.
(This was too much text, so dog picture.)
It's actually possible for us to get a to-the-block correct estimated balance for a user. We basically take the greater of the (total value in the contract / total ousd), divided by the number of total credits, times the user's credits. We could either make a convenience method in the vault contract to calculate this, or have majorhammers stream it live over websockets pubsub (reducing alchmey calls).
If we can get to the block correct estimate, what do we do in between? I don't know that is bad UI to have the counter only increment on every block. Every two to twenty seconds it turns green for a moment and rolls up. That might even be more addicting that a smooth roll.
Or we could do magic and diff the values between blocks and the timestamps and move based on those.
We should certainly improve the accuracy if we can get the estimate from the vault value instead of relying on post-rebase supply. @DanielVF how often does total value increase assuming no new mints and no rebases? For the portion allocated to a Compound strategy, I assume we can get an increase every block. But we wouldn't get increases that frequently from AMM strategies nor from reward token liquidations, of course. I suppose it's okay for the APY to be higher than the rate at which the estimated balance grows for most blocks. My preference would still be for a constant animation rather than the Compound-style animation per-block.
Our total value increases per block from compound. With AMM's we increase in value every time a transaction happens on the AMM. Other yield happens on harvests. Yield can also happen on redeems.
I think it's just fine for the actual APY to be higher than the displayed rate of increase. That slower rate is the moment by moment reality.
After discussing this with @matthewliu and @auregimon, I think we would prefer to keep the current animation and just do what we can to improve the experience for when people refresh their browsers. We would rather not increase the balance based purely on the Compound strategy earnings, which are likely to make up a small portion of the APY and may not even be a supported strategy at some point. We label the big number "Estimated", so I think it's okay for it to differ across devices. As a user, I would be more concerned with my balance not matching MetaMask or Etherscan (along with other portfolio management DApps). And that will be the case as long as we're displaying anything other than balanceOf
.
I think long-term, we're going to need to find a reason for rebase
to get called much more frequently whether people are minting or not. It's going to be an issue that affects more than just the displayed balance on our DApp.
@DanielVF the dog picture with the reason made me laugh out loud đŸ™‚
As for the animated balance solution, if other strategies do not provide a per block earnings that makes sense to me that we keep it as it is. And make it resilient on refreshes. Though I agree with @DanielVF that this is the most important piece of info the dapp serves and should probably assign a higher priority to it.
I also think (and would be cool to confirm this with user tests) that users won't all understand the estimated
balance label the way we assume. There is a lot of infrastructural knowledge we poses that users don't which could cause misunderstandings.
A few suggestions:
In the dapp we animate the OUSD balance by reading the current OUSD balance from the contract and simulating the current (incrementing) value by using the Apy returned by the Vault. While this gives users nice impression of OUSD balance increasing it has its shortcomings.
If a user refreshes the dapp or returns in 1-2 hours and rebase has not happened in the meantime the OUSD balance "resets" to the balance returned by the contract. A user would of course expect the balance to increase while he/she was away.
One suggestion how to tackle this would be to somehow get the
blockNumber
of the latest rebase transaction (or timestamp). Using that we could guess a more accurate approximate initial OUSD balance number.We could probably do that using the contract events, but we currently do not have a backend client listening for those kind of events and exposing data via API. We could also store the latest rebase timestamp on the Vault contract.
Perhaps there is a more elegant solution to this problem? cc: @DanielVF @tomlinton @micahalcorn