mirror of
https://github.com/luxfi/uma.git
synced 2026-10-30 15:14:44 +00:00
87 lines
3.9 KiB
Solidity
87 lines
3.9 KiB
Solidity
// SPDX-License-Identifier: AGPL-3.0-only
|
|
pragma solidity 0.8.16;
|
|
|
|
/**
|
|
* @title Computes vote results.
|
|
* @dev The result is the mode of the added votes. Otherwise, the vote is unresolved.
|
|
*/
|
|
library ResultComputationV2 {
|
|
/****************************************
|
|
* INTERNAL LIBRARY DATA STRUCTURE *
|
|
****************************************/
|
|
|
|
struct Data {
|
|
mapping(int256 => uint128) voteFrequency; // Maps price to number of tokens that voted for that price.
|
|
uint128 totalVotes; // The total votes that have been added.
|
|
int256 currentMode; // The price that is the current mode, i.e., the price with the highest frequency.
|
|
}
|
|
|
|
/****************************************
|
|
* VOTING FUNCTIONS *
|
|
****************************************/
|
|
|
|
/**
|
|
* @notice Adds a new vote to be used when computing the result.
|
|
* @param data contains information to which the vote is applied.
|
|
* @param votePrice value specified in the vote for the given `numberTokens`.
|
|
* @param numberTokens number of tokens that voted on the `votePrice`.
|
|
*/
|
|
function addVote(
|
|
Data storage data,
|
|
int256 votePrice,
|
|
uint128 numberTokens
|
|
) internal {
|
|
data.totalVotes += numberTokens;
|
|
data.voteFrequency[votePrice] += numberTokens;
|
|
if (votePrice != data.currentMode && data.voteFrequency[votePrice] > data.voteFrequency[data.currentMode])
|
|
data.currentMode = votePrice;
|
|
}
|
|
|
|
/****************************************
|
|
* VOTING STATE GETTERS *
|
|
****************************************/
|
|
|
|
/**
|
|
* @notice Returns whether the result is resolved, and if so, what value it resolved to.
|
|
* @dev `price` should be ignored if `isResolved` is false.
|
|
* @param data contains information against which the `minTotalVotes` and `minModalVotes` thresholds are applied.
|
|
* @param minTotalVotes min (exclusive) number of tokens that must have voted (in any direction) for the result
|
|
* to be valid. Used to enforce a minimum voter participation rate, regardless of how the votes are distributed.
|
|
* @param minModalVotes min (exclusive) number of tokens that must have voted for the modal outcome for it to result
|
|
* in a resolution. This is used to avoid cases where the mode is a very small plurality.
|
|
* @return isResolved indicates if the price has been resolved correctly.
|
|
* @return price the price that the dvm resolved to.
|
|
*/
|
|
function getResolvedPrice(
|
|
Data storage data,
|
|
uint128 minTotalVotes,
|
|
uint128 minModalVotes
|
|
) internal view returns (bool isResolved, int256 price) {
|
|
if (data.totalVotes > minTotalVotes && data.voteFrequency[data.currentMode] > minModalVotes) {
|
|
isResolved = true; // minTotalVotes and minModalVotes are exceeded, so the resolved price is the mode.
|
|
price = data.currentMode;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @notice Checks whether a `voteHash` is considered correct.
|
|
* @dev Should only be called after a vote is resolved, i.e., via `getResolvedPrice`.
|
|
* @param data contains information against which the `voteHash` is checked.
|
|
* @param voteHash committed hash submitted by the voter.
|
|
* @return bool true if the vote was correct.
|
|
*/
|
|
function wasVoteCorrect(Data storage data, bytes32 voteHash) internal view returns (bool) {
|
|
return voteHash == keccak256(abi.encode(data.currentMode));
|
|
}
|
|
|
|
/**
|
|
* @notice Gets the total number of tokens whose votes are considered correct.
|
|
* @dev Should only be called after a vote is resolved, i.e., via `getResolvedPrice`.
|
|
* @param data contains all votes against which the correctly voted tokens are counted.
|
|
* @return uint128 which indicates the frequency of the correctly voted tokens.
|
|
*/
|
|
function getTotalCorrectlyVotedTokens(Data storage data) internal view returns (uint128) {
|
|
return data.voteFrequency[data.currentMode];
|
|
}
|
|
}
|