The QVBaseStrategy
is a base contract for quadratic voting strategies. It extends the BaseStrategy
contract. It's designed to be a base contract for other contracts to inherit from. It includes functions for recipient registration, allocator allocation, and payout distribution. It also includes a review mechanism for pool managers to review and update the status of recipients. It uses a custom InternalRecipientStatus enum for internal state management. It has a strong focus on modularity and reusability, with many functions marked as virtual.
- QVBaseStrategy.sol
sequenceDiagram
participant Allocator
participant Alice
participant PoolManager
participant Allo
participant QVSimple
PoolManager->>Allo: createPool() with QVSimple
Allo-->>QVSimple: poolId
Alice->>+Allo: registerRecipient()
Allo-->>QVSimple: registerRecipient()
QVSimple-->>Allo: recipient1
Allo-->>-Alice: recipient1
PoolManager->>+Allo: reviewRecipients()
Allocator->>+Allo: allocate()
Allo-->>QVSimple: allocate() defined in contract inheriting QVBase
PoolManager->>+Allo: distribute()
Allo-->>-QVSimple: distribute()
- License: The
QVBaseStrategy
contract adheres to the AGPL-3.0-only License, promoting open-source usage with specific terms. - Solidity Version: Developed using Solidity version 0.8.19, leveraging the latest Ethereum smart contract advancements.
- Internal Libraries: Utilizes the
Metadata
library. - Interfaces: Interfaces with the
IAllo
andIRegistry
components for external communication. - Inheritance: Inherits from the
BaseStrategy
contract, inheriting and expanding core strategy functionalities.
Details of a recipient.
totalVotesReceived
(uint256): Total votes received by the recipientuseRegistryAnchor
(bool): Whether the recipient uses registry anchorrecipientAddress
(address): Address of the recipientrecipientStatus
(InternalRecipientStatus): Status of the recipientmetadata
(Metadata): Metadata details
Details of an allocator.
voiceCredits
(uint256): Total voice credits of the allocatorvoiceCreditsCastToRecipient
(mapping(address => uint256)): Voice credits cast to recipients by the allocator
registryGating
(bool, slot 0): Whether the strategy uses registry gating for recipient applications.metadataRequired
(bool, slot 0): Whether metadata is required for recipient applications.reviewThreshold
(uint256, slot 1): The number of votes required to review a recipient.registrationStartTime
(uint64, slot 2): The start time for recipient registration in milliseconds since the epoch.registrationEndTime
(uint64, slot 2): The end time for recipient registration in milliseconds since the epoch.allocationStartTime
(uint64, slot 2): The start time for vote allocation in milliseconds since the epoch.allocationEndTime
(uint64, slot 2): The end time for vote allocation in milliseconds since the epoch.
onlyActiveRegistration
: Allows execution only during the active registration period.onlyActiveAllocation
: Allows execution only during the active allocation period.onlyAfterAllocation
: Allows execution only after the allocation period has ended.
constructor(address _allo, string memory _name)
: Sets the Allo contract address and the strategy name.
initialize(uint256 _poolId, bytes calldata _data) external
: Initializes the strategy with provided parameters.
getRecipient(address _recipientId) external view returns (Recipient memory)
: Retrieves recipient details using recipient ID.getInternalRecipientStatus(address _recipientId) external view returns (InternalRecipientStatus)
: Retrieves internal recipient status using recipient ID.getRecipientStatus(address _recipientId) external view returns (RecipientStatus)
: Retrieves global recipient status using recipient ID.
updatePoolTimestamps(uint64 _registrationStartTime, uint64 _registrationEndTime, uint64 _allocationStartTime, uint64 _allocationEndTime) external
: Updates the start and end timestamps for the pool.reviewRecipients(address[] calldata _recipientIds, InternalRecipientStatus[] calldata _recipientStatuses) external
: Reviews recipient applications during the active registration.distribute(address[] calldata _recipientIds) external
: Distributes tokens to recipients after allocation.
_distribute(address[] storage _recipientIds, address _sender) internal
: Distributes tokens to recipients after allocation._isPoolActive() internal view returns (bool)
: Checks if the pool is currently active._getPayout(address _recipientId) internal view returns (PayoutSummary memory)
: Calculates the payout for a recipient._qv_allocate(Allocator storage _allocator, Recipient storage _recipient, address _recipientId, uint256 _voiceCreditsToAllocate, address _sender) internal
: Allocates voice credits to a recipient._isValidAllocator(address _allocator) internal view returns (bool)
: Checks if an allocator is valid._hasVoiceCreditsLeft(uint256 _voiceCreditsToAllocate, uint256 _allocatedVoiceCredits) internal pure returns (bool)
: Checks if an allocator has voice credits left._isAcceptedRecipient(address _recipientId) internal view returns (bool)
: Checks if a recipient is accepted._isProfileMember(address _anchor, address _sender) internal view returns (bool)
: Checks if a sender is a profile member._getRecipient(address _recipientId) internal view returns (Recipient storage)
: Retrieves recipient details using recipient ID._updatePoolTimestamps(uint64 _registrationStartTime, uint64 _registrationEndTime, uint64 _allocationStartTime, uint64 _allocationEndTime) internal
: Updates the start and end timestamps for the pool._sqrt(uint256 x) internal pure returns (uint256 y)
: Calculates the square root of a number using the Babylonian method.
* Recipients can submit their application to the pool strategy for registration.
* Recipients provide necessary data based on the strategy's requirements.
* The strategy checks if metadata is required and whether the recipient address is valid.
* Recipients can be accepted, rejected, or appealed based on the review process.
* If accepted, their status is updated and they are eligible for receiving votes.
* Allocators (participants) allocate voice credits to specific recipients during the active allocation period.
* Voice credits are allocated based on a quadratic voting algorithm.
* Voice credits are cast to recipients, contributing to their total votes received.
* Allocated voice credits cannot exceed available voice credits for the allocator.
* Recipients can receive voice credits based on the votes allocated to them by allocators.
* Recipients accumulate votes throughout the active allocation period.
* Total recipient votes are calculated as the sum of square roots of allocated voice credits.
* Accumulated votes contribute to determining recipients' payouts.
* After the allocation period ends, the strategy manager initiates the payout distribution.
* Payouts are distributed to recipients based on their accumulated votes and the total votes in the pool.
* The calculated payout amount is transferred to recipients' addresses.
* Once a recipient is paid out, their payout status is updated to prevent double payouts.
* The pool manager can update registration and allocation start and end times.
* These timestamps determine the active registration and allocation periods.
* The new timestamps are validated to ensure logical ordering and consistency.
* Pool managers can review recipient applications and update their statuses.
* Depending on the review threshold, recipients' statuses can change from pending to accepted or rejected.
* If the review threshold is met, recipient statuses are updated, allowing them to participate in voting or receive payouts.
* Users can query the status and details of recipients and allocators using their IDs or addresses.
* Recipient status, total votes received, and other relevant data can be retrieved.
* Allocator information such as voice credits allocated to recipients can be queried.
* Users can view the start and end times of the registration and allocation periods.
* The strategy checks the current time against these timestamps to determine active periods.
* The pool's active status changes based on whether the current time is within the registration or allocation period.