eosdac / eosdac-contracts

All the EOSDAC smart contracts
MIT License
19 stars 11 forks source link

Include custodian stake amount in voting and membership status #1

Closed lukestokes closed 4 years ago

lukestokes commented 5 years ago

Via Telegram

Michael Yeates admin, [Dec 19, 2018 at 2:20:33 PM]:
yeah - we probably should include them really
as well as for membership status

New staking design automatically takes care of this because all the balance is together in the token contract rather than being split across token and daccustodian contracts.

dallasjohnson commented 5 years ago

The contract data always has supported saving the staked amount by a candidate via the locked_tokens field on a candidate. Therefore I expect this issue is related more to the UI rather than the contract repo.

lukestokes commented 5 years ago

@dallasjohnson Sorry if I wasn't clear, I think the question was about if I have 10 liquid EOSDAC tokens and 100,000 staked tokens and I vote for a custodian, is my vote weight 10 or 100,010? Also, with that same 100,000 staked, if I transfer those 10 tokens out to a different account, am I still considered a member of the DAC with my staked tokens?

dallasjohnson commented 5 years ago

Ok, all votes are calculated based on the voting account balance. Staking is separated from you vote power. So if have 100000 liquid and 10 staked your vote power will be 100,000 not 100,010. On the second point you don’t need to stake to be a member of the dac and the only way to transfer those staked tokens is to unstake first so you have them back in your pool of 100,010 tokens. Then you can transfer wherever you like. Also keep in mind you cannot unstake until you have withdrawn as a candidate.

michaeljyeates commented 5 years ago

some candidates went out and bought exactly 35k tokens and then staked them to run for election, now they are no longer considered members until they get 0.0001 more eosdac tokens. i was thinking we could change the check for membership to include any tokens staked. voting might be more difficult

dallasjohnson commented 5 years ago

Afaik membership doesn’t care about your token balance you will just have no voting power. If anything it would be more useful to add the staked balance into someone’s vote power but that’s yet another table lookup on every transfer action so might bad for cpu usage.

michaeljyeates commented 5 years ago

I think we should move responsibility for staking to the token contract

Benefits are

  1. All membership statuses and voting when staked will just work without any special cases
  2. Adding native staking capability along with observers for stake balance changes will allow us to be much more flexible in the future on voting strategies which can be enabled with configuration.
  3. Custodian contract will still be in charge of if the tokens can be unstaked. It will assert during the unstake observation to prevent it from executing.
  4. Registering as a custodian will not require a token transfer which means that a user can use a minority permission for all DAC activities.
  5. The custodian contract will no longer hold tokens and will not need special permissions to transfer EOSDAC tokens.

Add the following actions to the token contract

stake(name account, asset quantity)

Will add an entry (or update existing one) to the stakes table. Will send a stakeobsv action to the custodian contract, or the vote weight contract if configured.

unstake(name account, asset quantity)

Will add an entry to the unstakes table with the unstake time and amount set. Multiple entries are allowed per account. The unstake time is calculated based on the account's staketime setting, if this is not set then it will fall back to the default time set in stakeconfig. Will send a stakeobsv action to the custodian contract, or the vote weight contract if configured.

staketime(name account, uint32_t unstake_time)

Will change the account's staketime parameter in the staketimes table. If the new value is less than the current value then the account must unstake all existing stakes (ie. the stake table must be empty for that user). If the value being set is less than the configured minimum value then it will fail. A deferred transaction will be sent to refund.

stakeconfig(stake_config config, symbol token_symbol)

Updates the config which consists of staking_enabled, default_time, min_time, action must have permission of authority account of DAC derived from the symbol.

refund(uint64_t unstake_id)

Will remove tokens from the unstaked entry matching the unstake_id if the unstake time has passed. Then it will subtract those number of tokens from the stakes table. This action can either be called by deferred transaction or manually if that fails.

Preventing staked transfers

If staking is enabled then the token contract will check staked balance when making a transfer and will assert if the amount being transferred is greater than the balance minus the amount staked.

Migration

eosDAC should install the new contract and enable staking with a 3 day unstake time. Then a new migratestake action which will transfer the stakes back to the users along with a forcestake action. This is a temporary action added to the token contract which will stake the tokens and require authority of the authority account.

dallasjohnson commented 5 years ago

@michaeljyeates Interesting idea and could help encapsulate more token related logic into one place. Just to clarify: with the stake action you suggested that should add to an existing entry (if there is one) where would the stake release timestamp get saved then? Would that subsequent staking extend the initial stake timestamp out out for all staked tokens or would additional staked tokens adopt the initial stake timestamp (which may have already passed)?

It feels like if you can stake more than once then a ledger of stakes would be needed which would contain {"staker": "mrstaker", quantity": "5.0000 EOSDAC", "locked_until" : "6June2020" } and then another simple table per user which could track the total staked amount used for vote_weight actions. which would be updated for each (un)stake action. Obviously this is pretty RAM hungry but each user may only have 1 entry for staking so it would most consuming for the required indices in the table to quickly access the required rows.

michaeljyeates commented 5 years ago

Yes, there is one stake entry per user and many potential unstake entries (but these will be short-lived)