Supporting Initiatives
Function Signature
function supportInitiative(
uint256 initiativeId,
uint256 amount,
uint256 lockDuration
) external returns (uint256 tokenId)Parameters
| Parameter | Type | Description |
|---|---|---|
initiativeId | uint256 | ID of the initiative to support (must exist and be in Proposed state) |
amount | uint256 | Amount of tokens to lock (in wei, e.g., 100000 * 1e18) |
lockDuration | uint256 | Duration to lock tokens, measured in intervals (must be ≤ maxLockIntervals) |
Returns
tokenId- An ERC721 NFT token ID representing your lock position
Token approval: callers must approve the Signals contract for amount on the underlying ERC20 before calling supportInitiative.
Participant Requirements
struct ParticipantRequirements {
address token; // Token used for eligibility checks
uint256 minBalance; // User must hold this many tokens right now
uint256 minHoldingDuration; // User must have held tokens for this duration (requires ERC20Votes)
uint256 minLockAmount; // Min tokens to lock when supporting (must be ≤ minBalance)
}- token: ERC20/IVotes token checked for eligibility (can differ from the underlying lock token).
- minBalance: User must currently hold this many tokens to be eligible to support
- minHoldingDuration: User must have held ≥ minBalance tokens for this many blocks in the past. Only works with ERC20Votes tokens that support checkpoints.
- minLockAmount: Minimum amount user must lock when supporting. Must be equal to or less than minBalance.
tokenmust be set (cannot beaddress(0)).minBalanceenforces a current balance requirement.minHoldingDurationenforces a historical balance check (requires ERC20Votes checkpoints ontoken).minLockAmountenforces a minimum lock size and must be ≤minBalance.
Note: Requires ERC20Votes tokens with checkpoint support for duration-based requirements.
Weight Calculation
Initial Weight Formula
initialWeight = amount * lockDurationWeight Decay
Linear Decay (Type 0)
weight = lockAmount * lockDuration - (lockAmount * elapsedIntervals * decayRate)
// Floored at lockAmount minimumExponential Decay (Type 1)
weight = initialWeight * (decayMultiplier ^ elapsedIntervals)
// Floored at lockAmount minimumWeight Floor
Weight never drops below the lock amount (nominal value) until the lock expires.
Lock Data Structures
TokenLock
struct TokenLock {
uint256 initiativeId; // Which initiative this supports
address supporter; // Original supporter address
uint256 tokenAmount; // Underlying tokens locked
uint256 lockDuration; // Duration in intervals
uint256 created; // Block timestamp of creation
bool withdrawn; // Redemption status
}LockData (ISignalsLock interface)
struct LockData {
uint256 referenceId; // Initiative ID
uint256 nominalValue; // Token amount
uint256 expires; // Expiry timestamp
uint256 created;
bool claimed;
}Query Lock Data
getTokenLock(tokenId)returns the full lock record.getLockData(tokenId)returns the standardizedISignalsLockview.
Events Emitted
event InitiativeSupported(
uint256 indexed initiativeId,
address indexed supporter,
uint256 tokenAmount,
uint256 lockDuration,
uint256 tokenId
)initiativeId: Which initiative was supportedsupporter: Your address (NFT recipient)tokenAmount: Amount of tokens lockedlockDuration: Lock duration in intervalstokenId: ERC721 token ID minted
Validation & Errors
| Error | Cause | Solution |
|---|---|---|
Signals_IncorrectBoardState | Board not open | Wait for board to open |
Signals_InvalidID | Invalid initiative ID | Use valid initiative ID |
Signals_IncorrectInitiativeState | Initiative not in Proposed state | Only support Proposed initiatives |
Signals_InvalidArguments | Duration > maxLockIntervals | Use valid duration |
Signals_InsufficientTokens | Balance < required | Acquire more tokens |
Signals_InsufficientLockAmount | Amount < minLockAmount | Increase lock amount |
Signals_TokenTransferFailed | Transfer failed | Check approval and balance |
Signals_InsufficientTokenDuration | Haven't held tokens long enough | Wait or use different account |
Signals_TokenHasNoCheckpointSupport | Token doesn't support IVotes | Board misconfigured |
Helper Functions
// Get all lock positions for an initiative
function locksForInitiative(uint256 initiativeId) external view returns (uint256[] memory)
// Get acceptance threshold
function getAcceptanceThreshold() external view returns (uint256)
// Get acceptance criteria
function getAcceptanceCriteria() external view returns (AcceptanceCriteria memory)Incentive Rewards
If an incentives pool is configured, credits are recorded on lock creation and rewards are paid during redemption after acceptance. The pool does not expose per-supporter previews.
