Skip to main content

TokenizedAllocationMechanism

Git Source

Inherits: IERC20

Title: TokenizedAllocationMechanism

Author: Golem Foundation

Shared implementation for allocation/voting mechanisms (Yearn V3 pattern)

Handles all standard voting logic via delegatecall from mechanism proxies

PROPOSAL STATE MACHINE:

Pending -> Active -> Tallying -> Defeated/Succeeded -> Queued -> Redeemable -> Expired

Canceled proposals leave the normal lifecycle as a terminal state.

STATE DESCRIPTIONS:

  • Pending: Proposal created, waiting for votingDelay
  • Active: Voting period active, users can cast votes
  • Tallying: Voting ended, waiting for finalization
  • Defeated: Voting ended, failed quorum
  • Succeeded: Voting ended, passed quorum
  • Queued: Shares minted, waiting for timelock
  • Redeemable: Timelock passed, within grace period
  • Expired: Grace period passed, redemptions closed
  • Canceled: Proposer canceled (terminal state)

LIFECYCLE TIMELINE:

  • T0: Proposal created (Pending)
  • T0 + votingDelay: Voting opens (Active)
  • T0 + votingDelay + votingPeriod: Voting closes (Tallying)
  • Anyone calls finalizeVoteTally(): Defeated or Succeeded
  • If Succeeded, anyone calls queue(): Queued (shares minted)
  • Queued + timelockDelay: Redeemable (redemptions allowed)
  • Redeemable + gracePeriod: Expired (redemptions closed)

VOTING MECHANICS:

  1. Users signup (deposit assets, get voting power)
  2. Proposals created during registration period
  3. Users cast votes (Against/For/Abstain)
  4. Votes finalized after votingPeriod
  5. Successful proposals get shares minted
  6. Recipients redeem shares for assets

SECURITY FEATURES:

  • Timelock: Delay before redemptions (security buffer)
  • Grace Period: Limited redemption window
  • Quorum: Minimum votes required
  • EIP-712: Gasless signups and votes
  • Reentrancy protection
  • Pausability

Notes:

  • security-contact: [email protected]

  • security: State machine enforces proper proposal progression

  • security: Timelock provides security delay before fund distribution

Quick Start — What Matters Most

This is the shared lifecycle implementation for all allocation mechanisms. It manages the round lifecycle from registration through redemption.

Key functions to understand:

  • signup — Users register and deposit assets
  • propose — Create funding proposals
  • castVote — Cast votes on proposals
  • finalizeVoteTally — Tally votes and determine winners (onlyOwner)
  • queueProposal — Mint shares for successful proposals

State Variables

MAX_SAFE_VALUE

Maximum safe value for internal math to avoid overflows

Capped at uint128.max to keep intermediate operations within safe bounds

uint256 public constant MAX_SAFE_VALUE = type(uint128).max

ALLOCATION_STORAGE_SLOT

Storage slot for allocation mechanism data (EIP-1967-like deterministic slot)

Calculated as keccak256("tokenized.allocation.storage") - 1 to minimize collision risk

bytes32 private constant ALLOCATION_STORAGE_SLOT = bytes32(uint256(keccak256("tokenized.allocation.storage")) - 1)

TYPE_HASH

EIP-712 Domain separator typehash

Used to compute domain separator for structured data signing

bytes32 private constant TYPE_HASH =
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")

SIGNUP_TYPEHASH

Signup typehash for EIP-712 structured data

Typed data: Signup(user, payer, deposit, nonce, deadline)

bytes32 private constant SIGNUP_TYPEHASH =
keccak256("Signup(address user,address payer,uint256 deposit,uint256 nonce,uint256 deadline)")

CAST_VOTE_TYPEHASH

CastVote typehash for EIP-712 structured data

Typed data: CastVote(voter, proposalId, choice, weight, expectedRecipient, nonce, deadline)

bytes32 private constant CAST_VOTE_TYPEHASH = keccak256(
"CastVote(address voter,uint256 proposalId,uint8 choice,uint256 weight,address expectedRecipient,uint256 nonce,uint256 deadline)"
)

EIP712_VERSION

EIP-712 version string used in domain separator

Update only with extreme caution; changing breaks signature domain

string private constant EIP712_VERSION = "1"

Functions

_getStorage

Get the storage struct from the predefined slot

function _getStorage() internal pure returns (AllocationStorage storage s);

Returns

NameTypeDescription
sAllocationStorageStorage struct containing all mutable state

constructor

Constructor to prevent initialization of the library implementation

constructor() ;

DOMAIN_SEPARATOR

Returns the domain separator, updating it if chain ID changed (fork protection)

function DOMAIN_SEPARATOR() public returns (bytes32);

_computeDomainSeparator

Computes the domain separator

function _computeDomainSeparator(AllocationStorage storage s) private view returns (bytes32);

onlyOwner

modifier onlyOwner() ;

whenNotPaused

modifier whenNotPaused() ;

nonReentrant

modifier nonReentrant() ;

initialize

Initialize the allocation mechanism with configuration

Can only be called once by the strategy/clone proxy; subsequent calls revert

Note: security: Initialization guarded by AlreadyInitialized check

function initialize(
address _owner,
IERC20 _asset,
string memory _name,
string memory _symbol,
uint256 _votingDelay,
uint256 _votingPeriod,
uint256 _quorumShares,
uint256 _timelockDelay,
uint256 _gracePeriod
) external;

Parameters

NameTypeDescription
_owneraddressAddress that will become the owner and management
_assetIERC20Underlying ERC20 asset used for deposits/redemptions
_namestringERC20 name for the shares token
_symbolstringERC20 symbol for the shares token
_votingDelayuint256Delay before voting opens (seconds)
_votingPerioduint256Duration of the voting phase (seconds)
_quorumSharesuint256Quorum threshold (shares, 18 decimals)
_timelockDelayuint256Delay after queueing before redemptions (seconds)
_gracePerioduint256Duration of redemption window (seconds)

_initializeAllocation

Internal allocation mechanism initialization

Shared initializer used by initialize

function _initializeAllocation(
address _owner,
IERC20 _asset,
string memory _name,
string memory _symbol,
uint256 _votingDelay,
uint256 _votingPeriod,
uint256 _quorumShares,
uint256 _timelockDelay,
uint256 _gracePeriod
) internal;

Parameters

NameTypeDescription
_owneraddressAddress that will become the owner and management
_assetIERC20Underlying ERC20 asset used for deposits/redemptions
_namestringERC20 name for the shares token
_symbolstringERC20 symbol for the shares token
_votingDelayuint256Delay before voting opens (seconds)
_votingPerioduint256Duration of the voting phase (seconds)
_quorumSharesuint256Quorum threshold (shares, 18 decimals)
_timelockDelayuint256Delay after queueing before redemptions (seconds)
_gracePerioduint256Duration of redemption window (seconds)

signup

Register to gain voting power by depositing underlying tokens

Note: security: Reentrancy protected; callable only when not paused

function signup(uint256 deposit) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
deposituint256Amount of underlying to deposit (asset base units, may be zero)

signupOnBehalfWithSignature

Register on behalf of another user using EIP-712 signature

The deposit will be taken from msg.sender, not the user. Increments nonces[user].

Note: security: Reentrancy protected; callable only when not paused

function signupOnBehalfWithSignature(address user, uint256 deposit, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external
nonReentrant
whenNotPaused;

Parameters

NameTypeDescription
useraddressAddress of the user signing up
deposituint256Amount of underlying to deposit (asset base units)
deadlineuint256Expiration timestamp for the signature (seconds)
vuint8Signature parameter
rbytes32Signature parameter
sbytes32Signature parameter

signupWithSignature

Register with voting power using EIP-712 signature

The deposit will be taken from the user themselves. Increments nonces[user].

Note: security: Reentrancy protected; callable only when not paused

function signupWithSignature(address user, uint256 deposit, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external
nonReentrant
whenNotPaused;

Parameters

NameTypeDescription
useraddressAddress of the user signing up
deposituint256Amount of underlying to deposit (asset base units)
deadlineuint256Expiration timestamp for the signature (seconds)
vuint8Signature parameter
rbytes32Signature parameter
sbytes32Signature parameter

_validateSignature

Validates signature parameters with ERC1271 support for contract signers

function _validateSignature(
address expectedSigner,
bytes32 structHash,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) private;

_executeSignup

Internal signup execution logic

function _executeSignup(address user, uint256 deposit, address payer) private;

propose

Create a new proposal targeting recipient

Note: security: Reentrancy protected; callable only when not paused; subject to strategy hook

function propose(address recipient, string calldata description)
external
whenNotPaused
nonReentrant
returns (uint256 pid);

Parameters

NameTypeDescription
recipientaddressAddress to receive allocated vault shares upon queue
descriptionstringHuman-readable description or rationale for the proposal

Returns

NameTypeDescription
piduint256Unique identifier for the new proposal

castVote

Cast a vote on a proposal

Note: security: Reentrancy protected; callable only when not paused; only during voting window

function castVote(uint256 pid, VoteType choice, uint256 weight, address expectedRecipient)
external
nonReentrant
whenNotPaused;

Parameters

NameTypeDescription
piduint256Proposal ID
choiceVoteTypeVoteType (Against, For, Abstain)
weightuint256Amount of voting power to apply (shares, 18 decimals)
expectedRecipientaddressExpected recipient address to prevent reorganization attacks

castVoteWithSignature

Cast vote using EIP-712 signature

Note: security: Reentrancy protected; callable only when not paused; only during voting window

function castVoteWithSignature(
address voter,
uint256 pid,
VoteType choice,
uint256 weight,
address expectedRecipient,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external nonReentrant whenNotPaused;

Parameters

NameTypeDescription
voteraddressAddress of the voter
piduint256Proposal ID
choiceVoteTypeVote choice (Against, For, Abstain)
weightuint256Voting weight to use (shares, 18 decimals)
expectedRecipientaddressExpected recipient address for the proposal
deadlineuint256Expiration timestamp for the signature (seconds)
vuint8Signature parameter
rbytes32Signature parameter
sbytes32Signature parameter

_executeCastVote

Internal vote execution logic

function _executeCastVote(address voter, uint256 pid, VoteType choice, uint256 weight, address expectedRecipient)
private;

finalizeVoteTally

Finalize vote tally once voting period has ended

Note: security: Only owner; reentrancy protected

function finalizeVoteTally() external onlyOwner nonReentrant;

queueProposal

Queue proposal and trigger share distribution

Note: security: Reentrancy protected; callable only after tally finalized and before redemption

function queueProposal(uint256 pid) external nonReentrant;

Parameters

NameTypeDescription
piduint256Proposal ID to queue

state

Get the current state of a proposal

function state(uint256 pid) external view returns (ProposalState);

Parameters

NameTypeDescription
piduint256Proposal ID

Returns

NameTypeDescription
<none>ProposalStateCurrent state of the proposal

_state

Internal state computation for a proposal with direct time range checks

function _state(uint256 pid) internal view returns (ProposalState);

cancelProposal

Cancel a proposal

Can only be called before vote tally is finalized. After finalization, all proposals are immutable.

This prevents race conditions and ensures coordinators can verify all proposals before committing.

function cancelProposal(uint256 pid) external nonReentrant;

Parameters

NameTypeDescription
piduint256Proposal ID to cancel

getProposalCount

Get total number of proposals created

function getProposalCount() external view returns (uint256);

name

Returns the mechanism name

function name() external view returns (string memory);

symbol

Returns the mechanism symbol

function symbol() external view returns (string memory);

asset

Returns the underlying asset

function asset() external view returns (IERC20);

owner

Returns the current owner

function owner() external view returns (address);

pendingOwner

Returns the pending owner awaiting acceptance

function pendingOwner() external view returns (address);

tallyFinalized

Returns whether vote tally has been finalized

function tallyFinalized() external view returns (bool);

proposals

Returns proposal data for a given proposal ID

function proposals(uint256 pid) external view returns (Proposal memory);

votingPower

Returns the voting power for a user

function votingPower(address user) external view returns (uint256);

proposalShares

Returns allocated shares for a proposal

function proposalShares(uint256 pid) external view returns (uint256);

startBlock

Returns the block number when mechanism was initialized

function startBlock() external view returns (uint256);

votingDelay

Returns the voting delay period in blocks

function votingDelay() external view returns (uint256);

votingPeriod

Returns the voting period duration in blocks

function votingPeriod() external view returns (uint256);

quorumShares

Returns the minimum shares required for quorum

function quorumShares() external view returns (uint256);

timelockDelay

Returns the timelock delay in seconds

function timelockDelay() external view returns (uint256);

gracePeriod

Returns the grace period duration in seconds

function gracePeriod() external view returns (uint256);

globalRedemptionStart

Returns the global redemption start timestamp

function globalRedemptionStart() external view returns (uint256);

votingStartTime

Returns the voting start timestamp

function votingStartTime() external view returns (uint256);

votingEndTime

Returns the voting end timestamp

function votingEndTime() external view returns (uint256);

startTime

Returns the mechanism start timestamp

function startTime() external view returns (uint256);

nonces

Returns the current nonce for an address

function nonces(address account) external view returns (uint256);

Parameters

NameTypeDescription
accountaddressAddress to check nonce for

Returns

NameTypeDescription
<none>uint256Current nonce for permit operations

transferOwnership

Initiate ownership transfer to a new address (step 1 of 2)

function transferOwnership(address newOwner) external onlyOwner;

Parameters

NameTypeDescription
newOwneraddressAddress to transfer ownership to

acceptOwnership

Accept ownership transfer (step 2 of 2)

Must be called by the pending owner to complete the transfer

function acceptOwnership() external;

cancelOwnershipTransfer

Cancel pending ownership transfer

Can only be called by current owner

function cancelOwnershipTransfer() external onlyOwner;

setKeeper

Update keeper address

function setKeeper(address newKeeper) external onlyOwner;

setManagement

Update management address

function setManagement(address newManagement) external onlyOwner;

pause

Emergency pause all operations

function pause() external onlyOwner;

unpause

Resume operations after pause

function unpause() external onlyOwner;

paused

Check if contract is paused

function paused() external view returns (bool);

sweep

Sweep remaining tokens after grace period expires

Can only be called by owner after global grace period ends

function sweep(address token, address receiver) external onlyOwner nonReentrant;

Parameters

NameTypeDescription
tokenaddressToken to sweep (use address(0) for ETH)
receiveraddressAddress to receive swept tokens

redeem

Redeems exactly shares from shareOwner and sends assets of underlying tokens to receiver.

Reverts with "ZERO_ASSETS" if shares amount rounds to 0 assets

Reverts with "redeem more than max" if shares > maxRedeem(shareOwner)

function redeem(uint256 shares, address receiver, address shareOwner) external nonReentrant returns (uint256);

Parameters

NameTypeDescription
sharesuint256Amount of shares to burn
receiveraddressAddress to receive withdrawn assets
shareOwneraddressAddress whose shares are burned

Returns

NameTypeDescription
<none>uint256assetsWithdrawn Actual amount of underlying withdrawn in asset base units

totalAssets

Get the total amount of assets this strategy holds as of the last report. We manually track totalAssets to avoid any PPS manipulation.

function totalAssets() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256totalAssets_ Total assets the strategy holds.

totalSupply

Get the current supply of the strategies shares. Locked shares issued to the strategy from profits are not counted towards the full supply until they are unlocked. As more shares slowly unlock the totalSupply will decrease causing the PPS of the strategy to increase.

function totalSupply() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256totalSupply_ Total amount of shares outstanding.

convertToShares

The amount of shares that the strategy would exchange for the amount of assets provided, in an ideal scenario where all the conditions are met.

function convertToShares(uint256 assets) external view returns (uint256);

Parameters

NameTypeDescription
assetsuint256Amount of underlying assets

Returns

NameTypeDescription
<none>uint256shares_ Expected shares that assets represent

convertToAssets

The amount of assets that the strategy would exchange for the amount of shares provided, in an ideal scenario where all the conditions are met.

function convertToAssets(uint256 shares) external view returns (uint256);

Parameters

NameTypeDescription
sharesuint256Amount of strategy shares

Returns

NameTypeDescription
<none>uint256assets_ Expected assets the shares represent in asset base units

previewRedeem

Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block, given current on-chain conditions.

This will round down.

function previewRedeem(uint256 shares) external view returns (uint256);

Parameters

NameTypeDescription
sharesuint256Amount of shares to redeem

Returns

NameTypeDescription
<none>uint256assets_ Amount of assets that would be returned in asset base units

maxRedeem

Total number of strategy shares that can be redeemed from the strategy by shareOwner, where shareOwner corresponds to the msg.sender of a redeem call.

function maxRedeem(address shareOwner) external view returns (uint256);

Parameters

NameTypeDescription
shareOwneraddressAddress that owns the shares

Returns

NameTypeDescription
<none>uint256_maxRedeem Maximum shares that can be redeemed

management

Returns the management address

function management() external view returns (address);

keeper

Returns the keeper address

function keeper() external view returns (address);

decimals

Returns the decimals used for the token (always 18)

function decimals() external pure returns (uint8);

balanceOf

Returns the balance of an account

function balanceOf(address account) external view returns (uint256);

allowance

Returns the allowance of a spender for a token owner

function allowance(address tokenOwner, address spender) external view returns (uint256);

_totalAssets

Internal implementation of totalAssets.

function _totalAssets(AllocationStorage storage S) internal view returns (uint256);

_totalSupply

Internal implementation of totalSupply.

function _totalSupply(AllocationStorage storage S) internal view returns (uint256);

_convertToShares

Internal implementation of convertToShares.

function _convertToShares(AllocationStorage storage S, uint256 assets, Math.Rounding _rounding)
internal
view
returns (uint256);

_convertToAssets

Internal implementation of convertToAssets.

function _convertToAssets(AllocationStorage storage S, uint256 shares, Math.Rounding _rounding)
internal
view
returns (uint256);

_maxRedeem

Internal implementation of maxRedeem.

function _maxRedeem(AllocationStorage storage S, address shareOwner) internal view returns (uint256 maxRedeem_);

_balanceOf

Internal implementation of balanceOf.

function _balanceOf(AllocationStorage storage S, address account) internal view returns (uint256);

_allowance

Internal implementation of allowance.

function _allowance(AllocationStorage storage S, address tokenOwner, address spender)
internal
view
returns (uint256);

_withdraw

To be called during redeem and withdraw. This will handle all logic, transfers and accounting in order to service the withdraw request.

function _withdraw(
AllocationStorage storage S,
address receiver,
address shareOwner,
uint256 assets,
uint256 shares
) internal returns (uint256);

transfer

Transfer '_amountof shares frommsg.sendertoto`.

Requirements:

  • to cannot be the zero address.
  • to cannot be the address of the strategy.
  • the caller must have a balance of at least _amount.
function transfer(address to, uint256 amount) external returns (bool);

Parameters

NameTypeDescription
toaddressAddress receiving the shares
amountuint256Amount of shares to transfer

Returns

NameTypeDescription
<none>boolsuccess True if operation succeeded

approve

Sets amount as the allowance of spender over the caller's tokens.

NOTE: If amount is the maximum uint256, the allowance is not updated on transferFrom. This is semantically equivalent to an infinite approval. Requirements:

  • spender cannot be the zero address. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an Approval event.
function approve(address spender, uint256 amount) external returns (bool);

Parameters

NameTypeDescription
spenderaddressthe address to allow the shares to be moved by.
amountuint256the amount of shares to allow spender to move.

Returns

NameTypeDescription
<none>boolsuccess True if the operation succeeded.

transferFrom

amount tokens from from to to using the allowance mechanism. amount is then deducted from the caller's allowance.

Emits an Approval event indicating the updated allowance. This is not required by the EIP. NOTE: Does not update the allowance if the current allowance is the maximum uint256. Requirements:

  • from and to cannot be the zero address.
  • to cannot be the address of the strategy.
  • from must have a balance of at least amount.
  • the caller must have allowance for from's tokens of at least amount. Emits a Transfer event.
function transferFrom(address from, address to, uint256 amount) external returns (bool);

Parameters

NameTypeDescription
fromaddressthe address to be moving shares from.
toaddressthe address to be moving shares to.
amountuint256the quantity of shares to move.

Returns

NameTypeDescription
<none>boolsuccess True if the operation succeeded.

_transfer

Moves amount of tokens from from to to. This internal function is equivalent to transfer, and can be used to e.g. implement automatic token fees, slashing mechanisms, etc. Emits a Transfer event. Requirements:

  • from cannot be the zero address.
  • to cannot be the zero address.
  • to cannot be the strategies address
  • from must have a balance of at least amount.
function _transfer(AllocationStorage storage S, address from, address to, uint256 amount) internal;

_mint

Creates amount tokens and assigns them to account, increasing the total supply. Emits a Transfer event with from set to the zero address. Requirements:

  • account cannot be the zero address.
function _mint(AllocationStorage storage S, address account, uint256 amount) internal;

_burn

Destroys amount tokens from account, reducing the total supply. Emits a Transfer event with to set to the zero address. Requirements:

  • account cannot be the zero address.
  • account must have at least amount tokens.
function _burn(AllocationStorage storage S, address account, uint256 amount) internal;

_approve

Sets amount as the allowance of spender over the owner s tokens. This internal function is equivalent to approve, and can be used to e.g. set automatic allowances for certain subsystems, etc. Emits an Approval event. Requirements:

  • owner cannot be the zero address.
  • spender cannot be the zero address.
function _approve(AllocationStorage storage S, address tokenOwner, address spender, uint256 amount) internal;

_spendAllowance

Updates owner s allowance for spender based on spent amount. Does not update the allowance amount in case of infinite allowance. Revert if not enough allowance is available. Might emit an Approval event.

function _spendAllowance(AllocationStorage storage S, address tokenOwner, address spender, uint256 amount)
internal;

Events

UserRegistered

Emitted when a user completes registration

event UserRegistered(address indexed user, uint256 votingPower);

Parameters

NameTypeDescription
useraddressAddress of the registered user
votingPoweruint256Voting power granted (shares, 18 decimals)

ProposalCreated

Emitted when a new proposal is created

event ProposalCreated(uint256 indexed pid, address indexed proposer, address indexed recipient, string description);

Parameters

NameTypeDescription
piduint256Newly assigned proposal id
proposeraddressAddress that created the proposal
recipientaddressIntended recipient of minted shares upon queue
descriptionstringHuman-readable proposal description

VotesCast

Emitted when a vote is cast

event VotesCast(address indexed voter, uint256 indexed pid, uint256 weight);

Parameters

NameTypeDescription
voteraddressAddress casting the vote
piduint256Proposal id being voted on
weightuint256Vote weight used (shares, 18 decimals)

VoteTallyFinalized

Emitted when vote tally is finalized

event VoteTallyFinalized();

ProposalQueued

Emitted when a proposal is queued and shares minted

event ProposalQueued(uint256 indexed pid, uint256 eta, uint256 shareAmount);

Parameters

NameTypeDescription
piduint256Proposal id being queued
etauint256Timestamp when timelock elapses and redemptions can begin (seconds)
shareAmountuint256Number of shares minted/allocated in share base units

ProposalCanceled

Emitted when a proposal is canceled

event ProposalCanceled(uint256 indexed pid, address indexed proposer);

Parameters

NameTypeDescription
piduint256Proposal id that was canceled
proposeraddressAddress of the canceling proposer

OwnershipTransferInitiated

Emitted when ownership transfer is initiated

event OwnershipTransferInitiated(address indexed currentOwner, address indexed pendingOwner);

Parameters

NameTypeDescription
currentOwneraddressCurrent owner address
pendingOwneraddressAddress nominated to become the new owner

OwnershipTransferCanceled

Emitted when ownership transfer is canceled

event OwnershipTransferCanceled(address indexed currentOwner, address indexed canceledPendingOwner);

Parameters

NameTypeDescription
currentOwneraddressCurrent owner address
canceledPendingOwneraddressPreviously pending owner whose transfer was canceled

OwnershipTransferred

Emitted when ownership is transferred

event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

Parameters

NameTypeDescription
previousOwneraddressAddress of the previous owner
newOwneraddressAddress of the new owner

KeeperUpdated

Emitted when keeper is updated

event KeeperUpdated(address indexed previousKeeper, address indexed newKeeper);

Parameters

NameTypeDescription
previousKeeperaddressOld keeper address
newKeeperaddressNew keeper address

ManagementUpdated

Emitted when management is updated

event ManagementUpdated(address indexed previousManagement, address indexed newManagement);

Parameters

NameTypeDescription
previousManagementaddressOld management address
newManagementaddressNew management address

PausedStatusChanged

Emitted when contract is paused/unpaused

event PausedStatusChanged(bool paused);

Parameters

NameTypeDescription
pausedboolTrue if paused, false if unpaused

GlobalRedemptionPeriodSet

Emitted when global redemption period is set

event GlobalRedemptionPeriodSet(uint256 redemptionStart, uint256 redemptionEnd);

Parameters

NameTypeDescription
redemptionStartuint256Timestamp when global redemptions can begin (seconds)
redemptionEnduint256Timestamp when global redemptions end (seconds)

Swept

Emitted when tokens are swept after grace period

event Swept(address indexed token, address indexed receiver, uint256 amount);

Parameters

NameTypeDescription
tokenaddressToken address that was swept
receiveraddressRecipient of swept tokens
amountuint256Amount swept in token base units

Withdraw

event Withdraw(
address indexed caller, address indexed receiver, address indexed owner, uint256 assets, uint256 shares
);

Parameters

NameTypeDescription
calleraddressAddress initiating the redemption
receiveraddressAddress receiving the underlying assets
owneraddressOwner of the shares being redeemed
assetsuint256Amount of underlying assets transferred (asset base units)
sharesuint256Amount of shares burned in share base units

Errors

ZeroAssetAddress

error ZeroAssetAddress();

ZeroVotingDelay

error ZeroVotingDelay();

ZeroVotingPeriod

error ZeroVotingPeriod();

ZeroQuorumShares

error ZeroQuorumShares();

ZeroTimelockDelay

error ZeroTimelockDelay();

ZeroGracePeriod

error ZeroGracePeriod();

ZeroStartBlock

error ZeroStartBlock();

InvalidStartTime

error InvalidStartTime(uint256 startTime, uint256 currentTime);

Parameters

NameTypeDescription
startTimeuint256Proposed start timestamp in seconds
currentTimeuint256Current block timestamp in seconds

EmptyName

error EmptyName();

EmptySymbol

error EmptySymbol();

RegistrationBlocked

error RegistrationBlocked(address user);

Parameters

NameTypeDescription
useraddressAddress attempting to register

VotingEnded

error VotingEnded(uint256 currentTime, uint256 endTime);

Parameters

NameTypeDescription
currentTimeuint256Current block timestamp in seconds
endTimeuint256Voting end timestamp in seconds

AlreadyRegistered

error AlreadyRegistered(address user);

Parameters

NameTypeDescription
useraddressAddress that is already registered

DepositTooLarge

error DepositTooLarge(uint256 deposit, uint256 maxAllowed);

Parameters

NameTypeDescription
deposituint256Deposit amount in asset base units (token decimals)
maxAlloweduint256Maximum allowed deposit in asset base units

VotingPowerTooLarge

error VotingPowerTooLarge(uint256 votingPower, uint256 maxAllowed);

Parameters

NameTypeDescription
votingPoweruint256Voting power in shares units in share base units
maxAlloweduint256Maximum allowed voting power in share base units

InsufficientDeposit

error InsufficientDeposit(uint256 deposit);

Parameters

NameTypeDescription
deposituint256Deposit amount in asset base units (token decimals)

ProposeNotAllowed

error ProposeNotAllowed(address proposer);

Parameters

NameTypeDescription
proposeraddressAddress attempting to propose

InvalidRecipient

error InvalidRecipient(address recipient);

Parameters

NameTypeDescription
recipientaddressInvalid recipient address

InvalidUser

error InvalidUser(address user);

Parameters

NameTypeDescription
useraddressInvalid user address

RecipientUsed

error RecipientUsed(address recipient);

Parameters

NameTypeDescription
recipientaddressRecipient with an active proposal

RecipientMismatch

error RecipientMismatch(uint256 pid, address expected, address actual);

Parameters

NameTypeDescription
piduint256Proposal id
expectedaddressExpected recipient address
actualaddressProvided recipient address

DescriptionMismatch

error DescriptionMismatch(uint256 pid);

Parameters

NameTypeDescription
piduint256Proposal id

EmptyDescription

error EmptyDescription();

DescriptionTooLong

error DescriptionTooLong(uint256 length, uint256 maxLength);

Parameters

NameTypeDescription
lengthuint256Provided description length in bytes
maxLengthuint256Maximum allowed length in bytes

VotingNotEnded

error VotingNotEnded(uint256 currentTime, uint256 endTime);

Parameters

NameTypeDescription
currentTimeuint256Current block timestamp in seconds
endTimeuint256Voting end timestamp in seconds

TallyAlreadyFinalized

error TallyAlreadyFinalized();

FinalizationBlocked

error FinalizationBlocked();

TallyNotFinalized

error TallyNotFinalized();

InvalidProposal

error InvalidProposal(uint256 pid);

Parameters

NameTypeDescription
piduint256Invalid proposal id

ProposalCanceledError

error ProposalCanceledError(uint256 pid);

Parameters

NameTypeDescription
piduint256Canceled proposal id

NoQuorum

error NoQuorum(uint256 pid, uint256 forVotes, uint256 againstVotes, uint256 required);

Parameters

NameTypeDescription
piduint256Proposal id
forVotesuint256Total for votes in share base units
againstVotesuint256Total against votes in share base units
requireduint256Quorum threshold in shares in share base units

AlreadyQueued

error AlreadyQueued(uint256 pid);

Parameters

NameTypeDescription
piduint256Proposal id

QueueingClosedAfterRedemption

error QueueingClosedAfterRedemption();

NoAllocation

error NoAllocation(uint256 pid, uint256 sharesToMint);

Parameters

NameTypeDescription
piduint256Proposal id
sharesToMintuint256Calculated shares to mint in share base units

InsufficientAssets

error InsufficientAssets(uint256 requested, uint256 available);

Parameters

NameTypeDescription
requesteduint256Assets requested in base units (token decimals)
availableuint256Available assets in base units (token decimals)

VotingClosed

error VotingClosed(uint256 currentTime, uint256 startTime, uint256 endTime);

Parameters

NameTypeDescription
currentTimeuint256Current block timestamp in seconds
startTimeuint256Voting start timestamp in seconds
endTimeuint256Voting end timestamp in seconds

InvalidWeight

error InvalidWeight(uint256 weight, uint256 votingPower);

Parameters

NameTypeDescription
weightuint256Vote weight in shares in share base units
votingPoweruint256Voter's voting power in shares in share base units

WeightTooLarge

error WeightTooLarge(uint256 weight, uint256 maxAllowed);

Parameters

NameTypeDescription
weightuint256Vote weight in shares in share base units
maxAlloweduint256Maximum allowed weight in shares in share base units

PowerIncreased

error PowerIncreased(uint256 oldPower, uint256 newPower);

Parameters

NameTypeDescription
oldPoweruint256Previous voting power in shares in share base units
newPoweruint256New voting power in shares in share base units

NotProposer

error NotProposer(address caller, address proposer);

Parameters

NameTypeDescription
calleraddressCaller address
proposeraddressExpected proposer address

AlreadyCanceled

error AlreadyCanceled(uint256 pid);

Parameters

NameTypeDescription
piduint256Proposal id

Unauthorized

error Unauthorized();

AlreadyInitialized

error AlreadyInitialized();

PausedError

error PausedError();

ReentrantCall

error ReentrantCall();

ExpiredSignature

error ExpiredSignature(uint256 deadline, uint256 currentTime);

Parameters

NameTypeDescription
deadlineuint256Signature deadline timestamp in seconds
currentTimeuint256Current block timestamp in seconds

InvalidSignature

error InvalidSignature();

InvalidSigner

error InvalidSigner(address recovered, address expected);

Parameters

NameTypeDescription
recoveredaddressAddress recovered from signature
expectedaddressExpected signer address

Structs

Proposal

Core proposal data used throughout the allocation mechanism

Stores immutable metadata for a proposal; dynamic tallies are kept elsewhere

struct Proposal {
/// @notice Number of shares requested if proposal succeeds in share base units
uint256 sharesRequested;
/// @notice Address that created the proposal
address proposer;
/// @notice Intended recipient of minted shares upon queue
address recipient;
/// @notice Human-readable description or rationale for the proposal
string description;
/// @notice True if the proposer canceled the proposal (terminal state)
bool canceled;
}

AllocationStorage

Main storage struct containing all allocation mechanism state

Stored at a deterministic slot; see ALLOCATION_STORAGE_SLOT

struct AllocationStorage {
// Basic information
/// @notice ERC20 name for the shares token
string name;
/// @notice ERC20 symbol for the shares token
string symbol;
/// @notice Underlying ERC20 asset used for deposits and redemptions
IERC20 asset;
// Configuration (immutable after initialization)
/// @notice Block number at initialization for legacy compatibility (blocks)
uint256 startBlock;
/// @notice Voting delay after start before voting opens (seconds)
uint256 votingDelay;
/// @notice Voting duration once opened (seconds)
uint256 votingPeriod;
/// @notice Timelock duration after queue before redemptions (seconds)
uint256 timelockDelay;
/// @notice Grace period during which redemptions are allowed (seconds)
uint256 gracePeriod;
/// @notice Quorum threshold in shares required for success in share base units
uint256 quorumShares;
/// @notice Mechanism start timestamp (seconds)
uint256 startTime;
/// @notice Timestamp when voting opens (startTime + votingDelay) (seconds)
uint256 votingStartTime;
/// @notice Timestamp when voting ends (startTime + votingDelay + votingPeriod) (seconds)
uint256 votingEndTime;
/// @notice Timestamp when {finalizeVoteTally} was called (seconds)
uint256 tallyFinalizedTime;
// Access control
/// @notice Current contract owner authorized to manage configuration
address owner;
/// @notice Pending owner waiting to accept ownership
address pendingOwner;
/// @notice Global pause flag to disable mutating actions
bool paused;
/// @notice True once {initialize} has been successfully called
bool initialized;
// Reentrancy protection
/// @notice Reentrancy guard flag (1 = NOT_ENTERED, 2 = ENTERED)
uint8 reentrancyStatus;
// Voting state
/// @notice True if vote tally is finalized (post-voting)
bool tallyFinalized;
/// @notice Monotonic counter used to assign new proposal ids
uint256 proposalIdCounter;
/// @notice Global timestamp when all redemptions and transfers can begin (seconds)
uint256 globalRedemptionStart;
/// @notice Global timestamp when the redemption period ends (seconds)
uint256 globalRedemptionEndTime;
// Allocation Mechanism Vault Storage (merged from DistributionMechanism)
/// @notice Per-address sequential nonces for EIP-712 signatures
mapping(address => uint256) nonces;
/// @notice Share balances per account in share base units
mapping(address => uint256) balances;
/// @notice Allowances mapping for share spenders in share base units
mapping(address => mapping(address => uint256)) allowances;
/// @notice Total number of shares in circulation in share base units
uint256 totalSupply;
/// @notice Total assets under management in underlying base units
/// @dev Manually tracked to prevent PPS manipulation through airdrops
uint256 totalAssets;
// Strategy Management
/// @notice Address permitted to perform keeper operations
address keeper;
/// @notice Management address authorized to update configuration
address management;
/// @notice Decimals used by asset and this shares token
uint8 decimals;
// Mappings
/// @notice Mapping from proposal id to stored {Proposal}
mapping(uint256 => Proposal) proposals;
/// @notice Tracks active proposal id for a given recipient (if any)
mapping(address => uint256) activeProposalByRecipient;
/// @notice Voting power per user in shares in share base units
mapping(address => uint256) votingPower;
/// @notice Shares allocated to each proposal in share base units
mapping(uint256 => uint256) proposalShares;
// EIP712 storage
/// @notice Cached EIP-712 domain separator for signatures
bytes32 domainSeparator; // Cached domain separator
/// @notice Chain id used in domain separator to provide fork protection
uint256 initialChainId; // Chain ID at deployment for fork protection
}

Enums

VoteType

Vote types for proposal voting

Used in castVote() to indicate vote direction

enum VoteType {
/// @notice Vote against the proposal
Against,
/// @notice Vote in favor of the proposal
For,
/// @notice Abstain from voting (recorded but doesn't affect outcome)
Abstain
}

ProposalState

Proposal lifecycle states

State machine progression enforced by contract logic

enum ProposalState {
/// @notice Created, waiting for votingDelay to pass
Pending,
/// @notice Voting period active, can cast votes
Active,
/// @notice Proposer canceled, terminal state
Canceled,
/// @notice Voting ended, awaiting finalization
Tallying,
/// @notice Finalized, failed quorum (terminal)
Defeated,
/// @notice Finalized, passed quorum, ready to queue
Succeeded,
/// @notice Shares minted, waiting for timelock
Queued,
/// @notice Timelock passed, in grace period (can redeem)
Redeemable,
/// @notice Grace period ended (redemptions closed)
Expired
}