Closed bufander closed 2 years ago
I think we should change the approach to something less gas intensive (for loops are expected to at least do around 10-20 iterations in this approach).
I will think through it and post alternatives
yes, I think you are right, we probably need to think of an alternative in which we can achieve a profit smoothing without needing so many operations
I think we should change the approach to something less gas intensive (for loops are expected to at least do around 10-20 iterations in this approach). I will think through it and post alternatives
yes, I think you are right, we probably need to think of an alternative in which we can achieve a profit smoothing without needing so many operations
analyzing a simpler way to update locking time, which I think makes sense.
After conversation with @jmonteer I've updated profit smoothing mechanism to a less gas intensive design.
We no longer store an array of profits, but only profit_end_date
(timestamp in which all profits are unlocked) and profit_distribution_rate
(a distribution rate computed with a proportional approach of new profits and time to unlock old profits. See link for full formula).
By using new design, updating the state is "cheap" but we are still smoothing the profit distribution through time to avoid front-running profits.
LGTM
Description
Implemented a smooth profit distribution mechanism.
Profits declared during
process_report
are locked and released linearly for a total length of seconds specified withprofit_unlock_time
(ie: for the full profit to be available for the users,profit_unlock_time
has to pass since the profit declaration).Losses declared in
process_report
are damped by existing profits in the buffer before affecting theprice_per_share
(reducingtotal_debt
). This reduces thedistribution_rate
of the existing profits.Important changes
update_profit_buffer()
: method in charge of updating theprofit_buffer
storage variable and the array with profits (profit_history
). It's called withprocess_report
,_deposit
and_redeem
to ensure all methods use the most up to date data.profit_buffer
storage variable: contains amount of profits locked. useprofitBuffer()
to retrieve value from Vault and estimate it if it's not updated.profit_history
storage variable: it's a DynArray with a maximum value that can be adapted with MAX_PROFITS_HISTORY. This value needs to be defined taking into consideration the amount of profits that can be declared concurrently within profit_unlock_time to avoid reaching the DynArray max size. (ie: concurrent profits during 7 days). Since Vyper 0.3.4,public
keyword cannot be used onDynArray
s, thats why we createget_profit_history
as a getter. Interesting to debug, understand and monitor the existing profits.process_report()
: during the declaration of profits/losses it will update the profit locking variables accordingly. It is where the locking happens.totalDebt()
: new method that overridestotal_debt()
getter (before it was automatically created by Vyper withpublic
keyword). This is because nowtotalDebt
needs needs to returntotal_debt
and to estimate the amount of profit that has been unlocked since profit locking variables where last updated. This allows us to always havetotalAssets()
(and thereforeprice_per_share
) returning the most up to date data, even if profit locking storage variables are not yet up to date.See economic scenarios in : smooth profit distribution mechanism - 64
Fixes #64
Checklist