Skip to main content

Vote requirements

Vote requirements are criteria used to determine whether a user has sufficient voting power to participate in a proposal.

How to add a new vote requirement

To add a new vote requirement, you must extend the votes.get_available_vote_requirements function.

Here is an example of how to add a new vote requirement:

struct native_chr_stake_vote_requirements_params {
required_balance: big_integer;
}

function validate_proposal_vote_requirement_parameters_for_native_chr_stake_requirement(params: byte_array) {
val native_chr_stake_vote_requirements_params = native_chr_stake_vote_requirements_params.from_bytes(params);
require(
native_chr_stake_vote_requirements_params
.required_balance > 0L,
"Required balance must be greater than 0"
);
}

function validate_vote_for_native_chr_stake_requirement(params: proposals.validate_vote_params): boolean {
val native_chr_stake_vote_requirements_params = native_chr_stake_vote_requirements_params
.from_bytes(
params
.extendable_vote_requirements
.params
);
return native_chr_stake_vote_requirements_params
.required_balance <= icmf.get_native_stake_balance(
params
.voter_account_id
);
}

function extract_native_chr_stake_vote_requirements_params(params: byte_array) {
return native_chr_stake_vote_requirements_params.from_bytes(params).to_gtv_pretty();
}

struct native_chr_stake_snapshot_balance_vote_requirements_params {
required_balance: big_integer;
snapshot_timestamp: timestamp;
}

function validate_vote_for_native_chr_stake_snapshot_requirement(params: proposals.validate_vote_params): boolean {
val native_chr_stake_snapshot_balance_vote_requirements_params = native_chr_stake_snapshot_balance_vote_requirements_params
.from_bytes(
params
.extendable_vote_requirements
.params
);
return native_chr_stake_snapshot_balance_vote_requirements_params
.required_balance <= icmf
.get_native_stake_balance_at_timestamp(
params
.voter_account_id,
native_chr_stake_snapshot_balance_vote_requirements_params
.snapshot_timestamp
);
}

function validate_proposal_vote_requirement_parameters_for_native_chr_stake_snapshot_requirement(params: byte_array) {
val native_chr_stake_snapshot_balance_vote_requirements_params = native_chr_stake_snapshot_balance_vote_requirements_params
.from_bytes(
params
);
require(
native_chr_stake_snapshot_balance_vote_requirements_params
.required_balance > 0L,
"Required balance must be greater than 0"
);
require(
native_chr_stake_snapshot_balance_vote_requirements_params
.snapshot_timestamp > 0L,
"Snapshot timestamp must be greater than 0"
);
}

function extract_native_chr_stake_snapshot_balance_vote_requirements_params(params: byte_array) {
return native_chr_stake_snapshot_balance_vote_requirements_params.from_bytes(params).to_gtv_pretty();
}

@extend(proposals.get_available_vote_requirements)
function icmf_get_available_vote_requirements(): map<text, proposals.my_vote_requirements> {
val vote_requirements = map<text, proposals.my_vote_requirements>();
vote_requirements.put(
"NATIVE_CHR_STAKE",
proposals.my_vote_requirements(
validate_vote = validate_vote_for_native_chr_stake_requirement(*),
validate_proposal_vote_requirement_parameters = validate_proposal_vote_requirement_parameters_for_native_chr_stake_requirement(
*
),
extract_params = extract_native_chr_stake_vote_requirements_params(*),
params = [
proposals.input_field(
name = "required_balance",
type = "big_integer",
label = "Required Native CHR Stake Balance",
required = true
)
]
)
);
vote_requirements.put(
"NATIVE_CHR_STAKE_SNAPSHOT",
proposals.my_vote_requirements(
validate_vote = validate_vote_for_native_chr_stake_snapshot_requirement(*),
validate_proposal_vote_requirement_parameters = validate_proposal_vote_requirement_parameters_for_native_chr_stake_snapshot_requirement(
*
),
extract_params = extract_native_chr_stake_snapshot_balance_vote_requirements_params(*),
params = [
proposals.input_field(
name = "required_balance",
type = "big_integer",
label = "Required Native CHR Stake Balance at Snapshot",
required = true
),
proposals.input_field(
name = "snapshot_timestamp",
type = "timestamp",
label = "Snapshot Time",
required = true
)
]
)
);

return vote_requirements;
}


The goal is to utilize extendable functions to return a map of vote requirements, similar to what is done with vote_power_strategies. Each result from the extended functions will be merged into a single map at execution time. You can refer to how extendable functions operate in Rell.

entity extendable_vote_requirements {
key proposal, name;
proposal;
name;
params: byte_array = x"";
}

struct extendable_vote_requirements_struct {
name;
params: byte_array;
}

struct validate_vote_params {
voter_account_id: byte_array;
extendable_vote_requirements;
locked_vote_power_amount: big_integer;
}

struct my_vote_requirements {
validate_vote: (validate_vote_params) -> boolean; // The first parameter is the voter, the second is the vote requirement parameters, and the third is the locked vote power amount
validate_proposal_vote_requirement_parameters: (byte_array) -> unit; // Validates the vote requirement parameters of a proposal
extract_params: (byte_array) -> gtv;
params: list<input_field>;
}

The extendable_vote_requirements entity is used to store the vote requirements for proposals that are created. In the vote requirements struct, you need to define the following properties:

validate_vote

The validate_vote function checks whether a user has enough voting power to cast a vote on a proposal. This function is called during the vote_on_proposal operation, and it must verify that the user's vote is eligible to be counted.

validate_proposal_vote_requirement_parameters

The validate_proposal_vote_requirement_parameters function validates the vote requirement parameters associated with a proposal.

extract_params

The extract_params function extracts the vote requirement parameters based on a specific vote requirement type.

params

The params field is a list of input fields that will be displayed in the user interface (UI).