Process for: RFC --> TC --> GP

Assets that translate to votes

XRD or LSUs

If XRD is used people argue that whales will dominate voting. With that said people suggested LSUs. But LSUs are liquid as well. Maybe not as liquid as XRD but still liquid due to the validators that offer instant unstake.

So if XRD and LSUs are liquid then which to use to register to vote? Which one best supports the RadixDLT network?

XRD is the token of the network. LSUs come from staking XRD to a validator. Anyone can spin up a validator and stake to it and get back LSUs. These LSUs could be from a validator that is not in the top 100.

Register to Vote

Registering to vote consists of taking an asset and locking it up for Z number of days / weeks. In return the registerer gets a badge or some marker - something that can be programmatically read in a component.

What asset to be used to register to vote is up for debate. Some say NO to XRD because it is too liquid - but LSUs are also liquid. I think because LSUs are liquid and because how the snapshot approach is getting complicated (read form here down Proposed Initial Governance Structure for the RadixDLT DAO DUNA (RDD) - #14 by octo and also the whole post) XRD as the asset to be used for voting should be back on the table.

The purpose of the “Register to vote” component is to stop an asset from being liquid and provide the voting system a way to fend off flash loans of LSUs or XRD in order to game voting.

Another argument against XRD is that those who have all theirs staked - they would have to unstaked to then register to vote.

Also, in a TC vote and or RIP vote there could be a “time elapsed” check. Meaning one who has a badge can only vote if they received the badge Y days ago.

Another dynamic could be different tiers of badges based on how many LSUs one registers to vote and for how long they lock them up. An argument against this would be is the validator goes down and the user wants to unstake from said validator.

For the sake of the rest of this post assume the user has registered their LSUs to get a voting badge or some kind of marker.

Request For Comments (RFC)

Anyone can create an RFC here on radixtalk. Feedback / comments and refinement of RFC lasts for X number of days.

Temperature Check (TC)

Anyone can create a TC so long as they have the needed badge / marker. Voting on the TC can be done by anyone so long as they have the needed badge / marker.

RadixDLT Improvement Proposal (RIP)

RadixDLT DAO Administrators (RDA) are the ones responsible for graduating a passed TC to a RIP. Voting on the RIP can be done by anyone so long as they have the needed badge / marker.

I agree with the flow, simple and effective.
We might need a bit more clarification as to what constitutes a successful TC outcome, so that it can be considered legit for RIP.

Re: the valid asset for voting, I still need to lay this out and do a risk matrix and find a solution :frowning:
It’s not just the economic/whaling considerations or the commitment level if using LSUs or not.

The root problem is still unanswered, imho: how do we avoid double voting power from same amount of XRD or LSUs?
It’s exactly the same issue with double spending, I guess … but we can’t afford to solve it with a consensus layer :sweat_smile:

I’ll circle back to this part.

But how are you double voting if there is a snapshot at a certain time of the LSU you hold?

If the snapshot is done once, the voting is based on that. How exactly you double vote? I don’t get it.
Because Instant unstake doesn’t help here.

Yes, the snapshotting solves almost everything … if it’s done the moment a new RPC is enacted (not open for voting, just created).
Yes, it also clears away inefficacies and edge cases from LSU manipulation (lending, instant unstake, etc) … for any given vote, if using LSUs.

But snapshots do not void asymmetry and gaming for “next voting”, i.e., if using LSUs, not all stakers stand an equal chance to have X voting power for the next vote … unless we make sure we void that asymmetry with careful time-bounds between consecutive voting snapshots.

And the issue with snapshots is also they’re not as trivial as ppl think - it has been discussed, there are some technical hurdles, it’s not like EVM-world - and, most important, there’s the issue of transforming the snapshot information into actual voting power, that needs an off-chain helper and a trustless way to record it on ledger and have the final voting-power list, per RFP, turstless on ledger as well.

What I infer from Jon’s attempt at this consolidated new topic is that we must further think and find a solution that enables a cleaner and more secure way of establishing voting power.

Unless, like also already referred to, we co-opt to use proof-of-personhood along with qualifying-asset to enable truly fair voting power … and that, in it self, besides needing technical solutions … also needs the community’s approval (it hasn’t been discussed proper or extensively and doesn’t fly, currently, to my knowledge)

1 Like

We would set some threshold of YES votes - if the TC passes that amount then it can be graduated to a RIP.

2 Likes

In the idea I shared above this would be solved like so:

  1. person registers their LSUs from their account (account_ABC)
  2. this locks up their LSUs (i will talk more about this lock up concept below)
  3. they get a badge set to the account used to register (account_ABC)
  4. they then use account_ABC to vote on a TC or RIP
  5. the component will not allow them to vote again on that specific TC / RIP because account_ABC already voted

LSU lock up

This may not need to be a thing because the badge and when the account got the badge is all that matters.

Examples where no lock up is used

  1. A TC is created
  2. In order to vote on the TC the user needs to have the special badge and must have received it before X days from when the TC was created

Take bob and tom. Bob gets wind that tom is going to propose a TC tomorrow. Bob wants to vote down the TC. He, right now, goes and get a bunch of LSUs, registers them, and gets the badge right now. It is now tomorrow and the TC is up but Bob cannot vote because his badge is too new.

In this scenario the badge and when the account got the badge holds all the power. At any time the user can get back their LSUs and have the badge removed from their account.

1 Like

I see … that you’re focusing on that “double vote” being on the same vote.
It’s not :swan:

In any case: if we do LSU (or any asset for that matter) lock up until the badge is used, then yes, my scenarios are more or less taken care of.
But this implies that voting requires temporary loss of asset ownership - I will elaborate on a possible solution for this next, based on what you describe.

If we totally want to avoid asset lockup/temporary loss of ownership, then it’s a different story … and the example you gave doesn’t solve the issues unless in very specific/strict conditions - more on that later as well.

So, for that lockup the asset scenario, here are some details, ideas and exploration:

Assumptions and/or design limitations:

Registering the base asset (let’s assume LSU will be the community’s choice, for now)

  • the goal of the registration is obtaining a “voting card” - could be a badge or an NFT, depends, more later on

  • the asset gets allocated to some vault that holds it until the “voting card” is used and can only be reclaimed later by original owner based on the “voting card” been used of the process has expired (voting ended but voting card was actually not used, all good)

The “voting card” represents the number of votes the base asset confers and can only be used in full, i.e, no fractional use - the vote is either full voting power or not used.

The “voting card” is souldbound, i.e, it can’t be transferred out of the wallet, can only be used and it’s either burned or recalled after use or expiration.

Each “voting card” is associated with a single RIP (proposal up for voting) and has the same expiration date/validity as the RIP voting process, can only be used to vote on that specific RIP.

Preferably, the return of the base asset to the original owner is done automatically, as well as the disposing “voting card” - this is easily done in Radix, I believe.

Challenges, Risks and Impacts

This presents a few challenges, even if it works as intended for the purpose of voting on that specific RIP.

1 - If several voting processes are being run in parallel or have any overlap, and each “voting card” is associated and valid only for one, then the holder is inhibited from properly voting in all of them per via of the base asset being locked up.

This requires that we either prohibit RIPs from overlaping at all … or we assume that voting isn’t universally guaranteed!

Or we come up with some strange way that allows to further add new RIPs to the same “voting card” … that would lead, potentially, to dragging the “voting card”’s validity in perpetual extention as each RIP is added. It becomes a nightmare to manage and can lead to even more edge cases!

None of the cases is acceptable, even if the first option could be initially considered to bootstrap the process and later changed when possible.

2 - It prevents the holder from freely exerting its ownership rights over the base asset (LSU) for the period of the lockup - it effectively prevents the user from unstaking and/or engage in DeFi operations that leverage the LSU, like use as collateral, etc.

IMHO this will not fly with the community, it’s too intrusive and bares additional risks because of the temporary custodial of the base asset. It becomes a detriment to usage of the LSUs in the ecosystem and effectively counteracts the very nature of LSUs being a native asset that can be used in the same way as the base token or anything other asset.

I much doubt the acceptance level of this choice and I sus that other hidden risks and edge scenarios that I’m not picturing rn can take place.

Alternatives and Mitigation

Instead of the custodial lockup of the asset, we could use a “soft-stake” approach (IOTA had this for voting, btw; it worked very well) where the asset is “frozen” in the wallet and cannot be moved from it, but still allows for any other usage that doesn’t require it - like registering for another RIP and any other possible usage that can use just proofs of ownership, for example.

This would efectively render this aproach usable … but I cannot imagine, at this point, what it would require in terms of protocol and/or additional components to enforce that “frozen” status.
Perhaps whatever can be used for it being “souldbound” can have am ephemeral nature and be turned on/off at will, unclear to me.

This requires some devs to look into the matter and check how it could be done.

Final Caveats

Regardless of the tech solution (if even possible), this scheme/process doesn’t account nor protects us from secondary/ancillary markets and economics … because anything that allows us to “freeze” the asset on the wallet at will also enables to same ancillary usage scenarios, where the asset, despite being frozen, can be used as collateral for lending XRD or LSUs and thus being effectively used to gain access to further voting power with the same underlaying asset’s reach being thus multiplied.
( I can elaborate further is needed, the whole ancillary and/or second level markets and economics are a real power in Radix … but they play against us in this :sweat_smile: )

If there’s an actual lockup with loss of ownership, i.e, the base asset is temporarily stored outside of the original wallet, then what I presented in point 1 of the challenges becomes real and it will not be acceptable, imho.

First off - thank you @projectShift for engaging in this discussion and brainstorming with me. I read both your posts above and thought about it for a bit and have come up with an idea.

Note that in the example below Bob first registers to vote, then votes, then adds more LSUs to his account and then tries to vote again.

RadixDLT DAO Voter Component

This component has two functions:

  • register
  • unregister - (this simply removes the badge - it’s more of a house cleaning thing for the account)

When someone (bob) registers to vote it is done from an account (in our example → account_BOB). In that register call the following are recorded:

  • total LSU count held by account_BOB (in our example 400 LSUs)
  • timestamp of when register was called (ie now)
  • if the account calling the register function already has the radixdlt_dao_voter badge then the above two records are simply updated to now and the account’s current total LSU count

In return acount_BOB is given a badge (radixdlt_dao_voter).

So in the voter component it now holds a record:

  • account_BOB
    • LSUs = 400
    • timestamp = “2026-01-21 05:22:27.133505Z”

and account_BOB has the radixdlt_dao_voter badge.

Note that no LSUs where locked up or frozen. Also note that the radixdlt_voter_badge can be used to vote on any TS and RIP. The radixdlt_voter_badge is not one time use per TC or per RIP - it can be used many times. The radixdlt_voter_badge cannot be sent to a different account.

RadixDLT DAO Voting Component

Below I share in detail about the guards / checks that must be passed before a vote can be successful.

The happy path is as follows.

A TC is created (TC#1) and is ready to be voted on. Bob (account_BOB) goes to vote on the TC. He calls the vote function and it checks the following before the vote can succeed:

  • account_BOB has not already voted on TC#1 :white_check_mark:
  • account_BOB has the radixdlt_dao_voter badge :white_check_mark:
  • account_BOB registered to vote on or before “2026-01-29” :white_check_mark:
  • account_BOB LSU count is less than or equal to 400 :white_check_mark:

vote successfully cast.

Now the NOT happy path. Assume some time goes by. BOB acquires 50 more LSUs at account_BOB.

A different TC is created (TC#2) and is ready to be voted on. Bob (account_BOB) goes to vote on the TC. He calls the vote function and it checks the following before the vote can succeed:

  • account_BOB has not already voted on TC#2 :white_check_mark:
  • account_BOB has the radixdlt_dao_voter badge :white_check_mark:
  • account_BOB registered to vote on or before “2026-01-29” :white_check_mark:
  • account_BOB LSU count is less than or equal to 400 :cross_mark: (he has 450 LSUs now) (note that the 400 came from the voter component record for account_BOB)

vote execution fails. Bob is not able to vote.


Recap

  • If Bob wants to vote he first needs to call register
  • How long in the past he registered plays a part in if he can vote on a TC or RIP (a TC or RIP may state that only those who acquired the radixdlt_dao_voter badge at least 14 days ago may vote)
  • If Bob adds LSUs to his account he will not be allowed to vote - he will need to call register again to update his record in the Voter Component
  • If Bob removes LSUs from his account - no problem
  • Bob is also welcome to add the new LSUs to a different account (account_BOB2) and register that and he would now vote with two accounts
  • Note that he would need to wait for account_BOB2 to reach maturity so he could vote with it

First, I’d like to reiterate that we want to keep things simple and flexible for now. The more logic you try to cram into the component, the less flexible you become. Since an RAC route is extremely likely, you are already bottlenecked by a “social layer”. If the RAC decides not to do something, it won’t happen until legal action is taken / the “no-confidence” process is strated. What this also means is that all vote counting and some other administrative slop can happen off-chain, or in a permissioned manner by the RAC. That makes developing the governance system simple, and enables keeping the end result flexible.

As for your specific proposal in Process for: RFC --> TC --> GP - #9 by jonericcook, registering at a certain timestamp makes little sense to me. Ask yourself, why would we want this? If everyone registers at a different timestamp, the data is unusable for proposals. If you want to GUARANTEE no double voting, you NEED to lock LSUs in some kind of Membership Card NFT. The solution where you just record for a certain timestamp doesn’t work.

You also cannot just query a user’s LSU amount within a Scrypto component: there are an infinite amount of LSUs if you accept all LSUs (not doable inside a single method call to query the user’s balance for all of them). Maybe you could let the method caller pass the LSUs they own as arguments, but this would quickly become a major PITA. Or, if you only accept LSUs in the active validator set, you need someone that constantly updates the governance component, to specify which LSUs are currently active (this is not trustless, and another PITA process).

It all makes little sense if we already have a perfectly fine way to measure someone’s voting power: off-ledger snapshots powered by the Gateway. It’s simple, we record someone’s vote on-ledger, but we count votes off-ledger. Changing which LSUs (or other (non) fungible tokens) are accepted is then also trivial: only a matter of passing a proposal, not an architectural change of the components. It keeps the immutable part of the logic - the Scrypto part, which once deployed cannot really be changed - minimal. That is what we should accomplish as a first version, imo.

That said, this might go into the weeds a little too deep, but since I’ve already created a high level spec of what I think the Scrypto blueprints could look like for my personal understanding, I’ll share it:

Consultation / Governance Scrypto Bluepints

Governance working will happen in a 3-part governance procedure:

  1. Request for Comment (RFC): A draft proposal, can be posted anywhere, such as RadixTalk (not on-chain)
  2. Temperature Check: Pushing all proposal details to chain, and voting on whether the proposal has enough merit to be officially voted on.
  3. Request for Proposal (RFP): A passed temperature check is elevated to an RFP, which can be voted on by the community.

Temperature checks and RFP votes are counted off-chain. The voting power of a user depends on their LSU holdings converted to XRD at the start of the vote!

Users can appoints delegatees that can vote in their stead.

Components

We will split data into two components:

  1. Governance component: holds all Temperature Check and RFP data. Is used to vote.
  2. VoteDelegation component: holds all info on delegators and delegatees.

The seperation is useful, because then we can upgrade the Governance component without delegators having to assign their delegation to a delegatee again. Modularity allows for upgrading only one part.

Governance component

Key Structs

// We can use https://github.com/thereturnofyo/radix-file-storage to store files like PDFs or .md files, which uses a struct like this to access files:
pub struct File {
  pub kvs_address: String,
  pub component_address: ComponentAddress,
  pub file_hash: String,
}

pub enum TemperatureCheckVote {
  For,
  Against,
}

// struct used to hold submitted temperature check data
pub struct TemperatureCheck {
  pub title: String,
  pub description: String, // short description
  pub vote_options: Vec<VoteOption>, // vote options for the proposed proposal (not for the temp check)
  pub attachments: Vec<File>,
  pub rfc_url: Url, // url pointing to RFC (which may go down, attachments are a backup)
  pub quorum: Decimal,
  pub votes: KeyValueStore<Global<Account>, TemperatureCheckVote>,
  pub approval_threshold: Decimal, // fraction of votes needed to be "for", for vote to pass
  pub start: Instant,
  pub deadline: Instant,
  pub elevated_proposal_id: Option<u64>,
}

// struct to use to submit a temperature check (passed to `make_temperature_check`)
pub struct TemperatureCheckDraft {
  pub title: String,
  pub description: String, // short description
  pub vote_options: Vec<ProposalVoteOption>, // vote options for the proposed proposal (not for the temp check)
  pub attachments: Vec<File>, // put a max on this to avoid state explosion
  pub rfc_url: Url, // url pointing to RFC (which may go down, attachments are a backup)
}

pub struct ProposalVoteOptionId(u32);

pub struct ProposalVoteOption {
  pub id: ProposalVoteOptionId,
  pub label: String, // "For", "Against", "Abstain"
}

pub struct Proposal {
  pub title: String,
  pub description: String, // short description
  pub vote_options: Vec<ProposalVoteOption>, // possible state explosion, will have max length
  pub attachments: Vec<File>, // put a max on this to avoid state explosion
  pub rfc_url: Url, // url pointing to RFC (which may go down, attachments are a backup)
  pub quorum: Decimal, // amount of XRD needed for proposal result to be valid
  pub votes: KeyValueStore<Global<Account>, ProposalVoteOptionId>
  pub approval_threshold: Decimal, // fraction of votes needed to be "for", for vote to pass
  pub start: Instant,
  pub deadline: Instant,
  pub temperature_check_id: u64,
}

pub struct GovernanceParameters {
  pub temperature_check_days: u16,
  pub temperature_check_quorum: Decimal,
  pub temperature_check_approval_threshold: Decimal,
  pub temperature_check_propose_threshold: Decimal, // XRD one must hold to do a temp check
  pub proposal_length_days: u16,
  pub proposal_quorum: Decimal,
  pub proposal_approval_threshold: Decimal,
  // no proposal_propose_threshold, elevation from temp check to rfp done by multi-sig member
}

// struct holding component state
pub struct Governance {
  pub governance_parameters: GovernanceParameters,
  pub temperature_checks: KeyValueStore<u64, TemperatureCheck>,
  pub temperature_check_count: u64,
  pub proposals: KeyValueStore<u64, Proposal>,
  pub proposal_count: u64,
}

Auth Roles

  1. OWNER: requires owner badge (could potentially be in possession of a multi-sig controlled account)
  2. PUBLIC

API

Method Access/Auth Input Output Description
instantiate() PUBLIC owner_badge: ResourceAddress
metadata_init: MetadataInit
component: Global<Governance> Instantiates the governance component with passed owner_badge as the owner role.
make_temperature_check() PUBLIC temperature_check: TemperatureCheckDraft id: u64 Create a temperature check with passed TemperatureCheck data, this is basically a proposal you think will pass (and doesn’t need changes). This is only done after completing the RFC phase (which happens off-ledger).

People vote on whether they want this temperature check to be elevated to a “real” proposal (RFP)
make_proposal() OWNER temperature_check_id: u64 id: u64 Elevate a temperature check to a “real” proposal (RFP). This needs admin power as to not spam the “real proposal” section.

People vote on the outcome of the proposal.
vote_on_temperature_check() PUBLIC
(checks passed account is present)
account: Global<Account>
temperature_check_id: u64
vote: TemperatureCheckVote
- Vote on whether you want a temp check to be elevated to an RFP.

You cannot change your vote midway.
vote_on_proposal() PUBLIC
(checks passed account is present)
account: Global<Account>
proposal_id: u64
vote: ProposalVoteOptionId
- Vote on an RFP.

You cannot change your vote midway.

VoteDelegation component

Key Structs

pub struct Delegation {
  pub delegatee: Global<Account>,
  pub fraction: Decimal,
  pub valid_until: Instant, // if a delegation is valid at the start of a vote, it is used for the vote
}

// component struct that holds state about delegatees and delegators
pub struct VoteDelegation {
  // key: delegatee (person allowed to vote for others)
  // value: KVS of delegators using this delegatee, and the fraction of their power allocated
  pub delegatees: KeyValueStore<Global<Account>, KeyValueStore<Global<Account>, Decimal>>,

  // key: delegator (person that has delegated their voting power to another)
  // value: Delegation struct, holds all the users delegations
  pub delegators: KeyValueStore<Global<Account>, Vec<Delegation>>
}

Auth Roles

  1. OWNER: requires owner badge (could potentially be in possession of a multi-sig controlled account), only used for stuff like metadata updates on the component.
  2. PUBLIC

API

Method Auth/Access Input Output Description
make_delegation() PUBLIC
(checks passed delegator is present)
delegator: Global<Account>
delegatee: Global<Account>
fraction: Decimal
valid_until: Instant (do we want this? or is this set in stone)
- Delegate your vote to another member (delegator gives power to delegatee).
remove_delegation() PUBLIC
(checks passed delegator is present)
delegator: Global<Account>
delegatee: Global<Account>
- Remove a delegation to another member (delegator removes power from delegatee).

Counting votes (off-chain)

To count votes, using an instantiated version of this blueprint, we need to:

  1. Query the TemperatureCheck’s / Proposal’s votes KVS, which gives a list of accounts that have voted, and their vote. We set their voting_power_fraction to 1.
  2. Query the VoteDelegation component’s delegatees KVS for all accounts that have voted: we check whether voted accounts also had the power to vote for others. We set the voting_power_fraction of these child accounts to whatever we find in the KVS.
  3. Query the VoteDelegation component’s delegators KVS for all accounts that have voted (including children of delegatees): we check which of the accounts that have voted were delegating (a part of) their vote at the state version corresponding with the start of the vote. We modify the voting_power_fraction of these accounts (subtract delegated power).
  4. Query the LSU holdings of all participating accounts (all voters + their delegators).
  5. Calculate the votes for every option using the collected data.

Note: an attentive reader might comment that the delegatees and delegators KVSs could grow HUGE. This might be a problem when wanting to read the entire KVSs. However, we never need to read the entire KVSs, since we only need data for accounts that voted (and their children).

The amount of votes on a proposal should remain limited and managable. If a malicious actor starts voting like crazy, we need to somehow add sybil protection to the voting part.

3 Likes

I’ll need time to digest all of this, lol

Thank you for the detailed sharing though.

One thing popped up immediately, though:

LSU holdings converted to XRD at the start of the vote!

LSU’s actual XRD value differs depending on the validator in question … you would have to both check for validator being in the set and then get accurate XRD valuation based on the actual LSU’s current metrics!

Isn’t this a nightmare, even if done off-chain??

Why can’t vote power be direct on LSU count? :thinking:

I’ll also need time to proper process this … but the short version is that it won’t work as intended and it is, indeed, over complicated already, just from description.

I’ll take Octo’s word that it’s also not the right way to do it, technically, in terms of Scrypto and RE, as I do not have the adequate expertise.

The “voting card” base idea is still usabale, like Octo’s comment also shows, but the right way to do it … clearly a path we must find.

I’ll try to draft smtg on it as well, but only high-level functional, no coding :smiley:

1 Like

Isn’t this a nightmare, even if done off-chain??

No :slightly_smiling_face: Quite easy even.. You only have to divide the total staked XRD on a validator by the total supply of its LSU. That is the XRD value per LSU unit.

The whole snapshot approach is relatively easy to build. Built it during Olympia for Astrolescent for the initial votes for the AstrelescentDAO but never got to the point launching the DAO. It’s quite a bit of work, but not complicated.

5 Likes

You want to introduce smart contract risk and lock ups for voting on proposals? The only viable solution I see is to use LSUs to vote. Holding LSUs means you have staked xrd to the network and have skin in the game to help secure it.

Registering and locking up stake has little purpose and just comes with risks and unnecessary complexity. One snapshot that gets taken before each vote will show what accounts hold what LSUs and can use that LSU amount to vote on whatever proposal. This is very simple, straightforward and will also allow votes in parallel. If you are worried about someone staking a bunch of LSUs before a vote you shouldn’t. That is a GOOD thing.

We have a tiny MC. Anyone who wants to gobble up some XRD, stake it, and have more influence on DAO decisions can do so now.

5 Likes

Thank you @octo for the detailed write up. I will go back through it a few more times. One thing I would like to highlight is the naming / terminology used. I wrote this up Naming / Terminology but also want to share here.

I believe RFP is not the correct term to be used here. From my research an entity submits an RFP when it wants proposals to be submitted. For example, an architectural firm would submit an RFP to contractors. The RFP is a top down concept. It would make sense for the RadixDLT DAO to create an RFP for a new gateway and community members would have the opportunity to submit an RFC (referencing the RFP) and then a TC and then a RIP.

3 Likes

Would it make sense for the RDAs (RadixDLT DAO Administrators) to be able to change how many accounts someone can delegate their vote power to?

I agree, in principle, with this, but I worry on the transient nature of the snapshot.

It’s a simple, elegant and every usable solution, allows for multi-voting in parallel and it’s very auditable, so the only thing that’s missing is getting its results into the ledger so we can have a simplified record instead of needing the state history to constantly rebuild the snapshot if we need to verify smtg.

It does need to be 1 snapshot per voting, though, because things constantly change so the next vote, even if only a couple hours apart, can already have significant differences.

And as I referred previously, we need to do smtg about the LSUs that are temporarily under custody, for whatever reason, as to avoid conferring voting ability to smtg that isn’t a simple wallet and may be abused by the custodial controller. No big deal to pull, technically, I believe, but still necessary to be done.

it also (mostly) avoids any ancillary market issues, because no one can trade its position/status in the snapshot :slight_smile:

But it’s not, contrary to what you state, a good proxy/proof of the commitment of the holder.
Actually, it could easily promote a very dynamic and constant shifting of voting power, where ppl can optimize the ownership of the LSUs for short periods pertaining each voting and immediately unstake to recover full liquidity.

My concern comes from this becoming a practice, where ppl only commit to have the LSUs around the time they infer or sense or are sure there’s a voting event they want to participate in and get rid of them immediately after the snapshot is confirmed.

This could have a direct impact on network’s security, given that LSUs represent the actual amount of XRD that’s committed to secure the network. Instead of having a more or less smooth dynamic of LSU creation and destruction, we could have a double spike event around each snapshotting/voting time/period.

The unstake period isn’t a guarantee because of the instant-unstake options out there - not only it creates asymmetry amongst LSUs dependent on validator used, it also incentivizes stake concentration in the subset of validators that enjoy such a status from the various platforms by ways of the LSUs now having another function that’s important - it shifts the basic dynamics they were designed for by via of that new role … and I don’t think we’re properly checking for the exact impact it can have.

You mention this to be a good thing, but I’m not so sure.

The simple straightforward example of more stake that’s kept because someone wants to have X amount of voting power is the only beneficial scenario - but you seem to be assuming that’s the natural dominant choice and that it will prevail.

I worry that’s just not the case, and LSU’s new shining role of voting power could easily become more relevant than the original role and bring about new, yet unknown dynamics that could backfire.

RIP is an acronym that I almost never hear or use, better RFC - TC - RFP

2 Likes

Counting Temperature checks and RFP votes off-chain it is certainly much simpler, easier and also verifiable.

if anything, if someone wanted to say that the vote should be weighted then the LSUs could be counted at the beginning and at subsequent time intervals until the end of the voting time.

this could be useful also if we want to split the voting power between two different and concurrent RFP

Sure, the voting process should be simple at least at the beginning, nothing stops us from changing it later

2 Likes

But RFC is not the correct term for a community member submitting something that can be voted on and then executed

I am not able to find a DAO that uses RFP as the final step