core-contracts
core-contracts copied to clipboard
[enhancement] calling unstake locks previously available funds
Steps to reproduce:
- deposit and stake tokens e.g. 100
- deposit more tokens but do not stake them e.g. 50
- withdraw tokens e.g. 25 works
- now call
unstake
with any amount of tokens e.g. 1 - cannot withdraw remaining amount of unstaked tokens e.g. 25 does not work
What was expected (based on example amounts above):
staked: 75
unstaked: 26
unavailable for withdrawal until unstaked_available_epoch_height
: 1
available for immediate withdrawal: 25
What happened:
staked: 75
unstaked: 26
unavailable for withdrawal until unstaked_available_epoch_height
: 26
available for immediate withdrawal: 0
I believe this is due to the unstaked
balance being treated as a single contiguous balance of tokens with the restrictions imposed by unstaked_available_epoch_height
of the Account.
Another example is receiving rewards and "taking profits" continuously. If you repeatedly call unstake
before withdraw
, you will have an unstaked balance that can never be withdrawn.
Why is this a bug? People should have access to funds as they are unstaked and past the available epoch for each unstaking.
Proposal:
Treat each unstaking as it's own balance with it's own unstaked_available_epoch_height
. Offer a method to calculate unstaked_available_balance
and unstaked_pending_balance
that returns funds available for withdraw immediately and funds that are still waiting for the available epoch height respectively.
Right now, pool doesn't track what's the amount locked due to rewards and what amount is unlocked for a long time. It's not easy to keep track for more than 1 balance, because the implementation has to track when each balance was unstaked. Then use them for restaking in proper order.
Doable, but not simple.
From a customer's perspective, I would flag this issue a critical bug (not enhancement) because funds are being locked and withheld longer than they should be because of unstaking side effects. In addition to deposited funds getting locked up because of unstaking side effect, as @evgenykuzyakov has pointed out, the release epoch gets recomputed and pushed out for the "total" unstaked funds each time funds are unstaked.
For example, if I requested 100 NEAR to be unstaked 3 epochs ago, and then request an additional 50 NEAR to be unstaked, then the total 150 NEAR will be locked up for another 4 epochs. The 100 NEAR should be available in the next epoch, but because of the unstaking side effect, they are withheld for a total of 7 epochs (instead of 4). From a customer point of view, this would not be desirable or logical. From the customer's point of view the 2 unstaking "transactions" should be independent of each other. The second transaction should not be interfering with the first transaction.
... as a side note, this also opens up a whole other can of worms ... as the name implies, core contracts are core and what's the strategy or plan to rollout new versions ... but that's a whole other discussion