agora/docs/tech-design/staking-pool.md
2022-02-02 13:59:34 +00:00

3.5 KiB

Staking pool technical design

Specification Status Implementation status Last revision
WIP WIP 2022-02-2022

Specification ownership: Emily Martins

Authors:

Implementation ownership: Emily Martins


The StakingPool

In order to be able to count votes at all, some means of proving a user's skin in the game on-chain must exist. We propose having a central StakingPool contract which mints separate per-user UTXOs in which the governance token can be deposited. The MintingPolicy of the state threads ensures that it is paid to the script and with valid initial state. This circumvents the need for a central token, and makes the minting of such tokens concurrently possible.

Peter, 2022-01-24: "(...) mints separate per-user UTxOs (...)": I think this should read something like "locks per-user continuing UTxOs carrying unique state-thread tokens in which the governance token can be deposited." What do you think?

Stake UTXOs

A stake UTXO stores the information to allow accessing your staked GT as if it was a safe.

data Stake = Stake
  { -- | Which proposals has this Stake been used to vote on?
    lockedByProposals :: [(DatumHash, ProposalVote)]
  , -- | The amount staked by this utxo
    stakedAmount :: GT
  , -- | Who owns this Stake
    owner :: PubKeyHash
  }

Peter, 2022-01-24: What happens is lockedByProposals grows too large? I know its unlikely, but have you considered devising a way circumvent this from being a possibility?

When voting for a proposal, the Stake UTXO is used to witness the user's staked amount. As a result, the two following state transitions take place (pseudocode):

proposal.votes += (stake.stakedAmount, vote)
stake.lockedByProposals += (hash proposal.settings, vote)

A sort of mutual binding between the proposal and the stake is created and undoing one undoes the other, which is exactly what we want!

Depositing and withdrawing is made illegal when stake.lockedByProposals isn't empty. Withdrawing is illegal so that you can't have GT in a vote, without having it anymore, whereas Depositing is illegal so that you can't deposit after a vote and unvote it again in order to retract more than you originally voted. Thus preserving that

Peter, 2022-01-24: "Thus preserving that..." (incomplete sentence)

Delegating stake

Most things like Cosigning sort of work trivially by just witnessing Stake, but delegation requires an extra step. We add a field to what Stake stores.

data Stake = Stake
  { -- | Which proposals has this Stake been used to vote on?
    lockedByProposals :: [(DatumHash, ProposalVote)]
  , -- | The amount staked by this utxo
    stakedAmount :: GT
  , -- | Who can spend our utxo for us when voting
    delegatedTo :: Maybe ValidatorHash
  , -- | Who owns this Stake
    owner :: PubKeyHash
  }

We simply link one stake to another. When voting now the voter can check which Stake utxos are delegated to them off-chain, and include them in the transaction for voting. This will lock the delegators' utxos, but that's no big deal because they can themselves unlock it just like usual. The validity of the hash provided to the Stake is irrelevant. It simply delegates its authentication to the particular hash. Note, it only delegates authentication for voting but not for example for withdrawing.