Actioning and Expiring Initiatives
Board owners have two key functions to manage initiative lifecycle: accepting successful proposals and expiring inactive ones. Both actions are permanent and trigger different outcomes for supporters.
Initiative States
enum InitiativeState {
Proposed, // Initial state when created
Accepted, // Approved via acceptInitiative
Cancelled, // Reserved for future use
Expired // Owner expired due to inactivity
}State Transitions
Valid Transitions
Proposed → Accepted (via acceptInitiative)
Proposed → Expired (via expireInitiative)Invalid Transitions
- Cannot expire an Accepted initiative
- Cannot accept an Expired initiative
- Cannot transition to Cancelled state (reserved for future use)
- Cannot reverse Accepted or Expired back to Proposed
Actioning an Initiative
Actioning an initiative means officially approving it, transitioning it from Proposed to Accepted state. This records the acceptance timestamp and makes locked tokens redeemable after any release timelock.
Access Control
Access control is determined by the board's AcceptanceCriteria:
struct AcceptanceCriteria {
AcceptancePermissions permissions; // Permissionless or OnlyOwner
ThresholdOverride thresholdOverride; // None or OnlyOwner
uint256 thresholdPercentTotalSupplyWAD;
uint256 minThreshold;
}Permission Settings
| permissions | thresholdOverride | Who Can Accept | Threshold Check |
|---|---|---|---|
OnlyOwner | None | Owner only | Required |
OnlyOwner | OnlyOwner | Owner only | Owner bypasses |
Permissionless | None | Anyone | Required for all |
Permissionless | OnlyOwner | Anyone | Owner bypasses, others required |
Pre-conditions
- Initiative must exist -
initiativeId <= initiativeCount - Initiative must be in Proposed state - Cannot accept already Accepted or Expired initiatives
- Caller must have permission - Based on
permissionssetting - Threshold must be met - Unless caller is owner with
ThresholdOverride.OnlyOwner
Threshold Calculation
The acceptance threshold is dynamically calculated:
threshold = max(
totalSupply * thresholdPercentTotalSupplyWAD / 1e18,
minThreshold
)At least one of these values must be non-zero.
What Happens When Accepting
When an initiative is accepted:
- State changes to
Accepted(irreversible) - Acceptance timestamp is recorded (
acceptanceTimestamp = block.timestamp) - Supporters can redeem their locked tokens (after release timelock)
Automatic Integrations
Incentives
If an incentives pool is configured, rewards are calculated and paid when supporters redeem their locks after acceptance.
Impact on Token Locks When Accepted
Redemption Timeline
Locked tokens become redeemable based on releaseLockDuration:
Immediate Release (releaseLockDuration = 0): Supporters can redeem immediately.
Timelocked Release: Supporters must wait for acceptanceTimestamp + releaseLockDuration before redeeming.
Board Cancellation: If the board is cancelled via cancelBoard(), the release timelock is bypassed and all locks become immediately redeemable.
Expiring an Initiative
Expiring an initiative terminates an inactive proposal that has failed to gain sufficient support. No additional support can be added, and the initiative is removed from active consideration. Tokens locked in support of an expired initiative can be redeemed immediately.
Access Control
Owner-only - Uses onlyOwner modifier. Only the board owner can expire initiatives.
Pre-conditions
- Initiative must exist
- Initiative must be in Proposed state - Cannot expire Accepted initiatives
- Initiative must be inactive for >
inactivityTimeout(default 60 days)
lastActivityupdates when:- Initiative is created
- Any supporter locks tokens
- Default timeout: 60 days (configurable via board config)
What Happens When Expiring
- State changes to
Expired - Emits
InitiativeExpiredevent - Supporters can redeem their locked tokens immediately (no waiting period)
- No incentive rewards are distributed for expired initiatives
Events
event InitiativeAccepted(uint256 indexed initiativeId, address indexed actor)
event InitiativeExpired(uint256 indexed initiativeId, address indexed actor)