Kalium DAO v1 Smart Contract: Technical Documentation
Version: 1.0
Compiler: Solidity ^0.8.20
License: MIT
Maintainer: Kalium DAO Administration
Overview
The Kalium DAO v1 smart contract introduces a cost-optimised governance structure for decentralised organisations. Designed to minimise gas costs while retaining essential DAO functionalities, this contract supports:
- Token-based participation
- Lightweight identity via custom identifiers
- Batch voting by an authorised operator
- Dynamic fund accumulation via discretionary allotments
- Owner-managed execution and treasury access
This documentation describes the design rationale, technical implementation, and operational constraints of each module within the contract.
Key Enhancements in v1
- Discretionary Allotments decoupled from individual proposals; managed globally.
- Compact vote tracking using signed int32values.
- Gas savings through tightly packed storage and custom errors.
- Batch voting optimisation with skipped entries for zero-token or duplicate votes.
Contract Architecture
Ownership Model
The DAO contract enforces centralised administrative control via an immutable owner address set during deployment. All critical functions, proposal creation, batch voting, economic parameter adjustment, and fund withdrawals, are restricted to the owner.
modifier onlyOwner() {
    if (msg.sender != owner) revert NotOwner();
    _;
}This centralisation is a deliberate tradeoff, suitable for DAOs operated by a core team while member input is captured democratically via token-weighted votes.
Token Economy
assignTokens
Allows any external user to acquire DAO tokens using ETH. Each user submits a bytes6 member ID and sends ETH proportional to the current tokenPrice.
function assignTokens(bytes6 memberID) external payableMechanics:
- Calculates tokens as msg.value / tokenPrice.
- Minimum purchase is 1 token.
- Fails with InsufficientEther()otherwise.
- Stores tokens in memberTokens[memberID].
- Emits: TokensPurchased(memberID, amount)
updateTokenPrice
Owner-only function to update the global token price.
function updateTokenPrice(uint256 newPrice) external onlyOwner- Price must be non-zero and different from the current one.
- Emits: TokenPriceUpdated(newPrice)
- Fails with: InvalidPrice()
Proposal Lifecycle
Proposal Structure
struct Proposal {
    uint32 end;
    uint48 votesFor;
    uint48 votesAgainst;
}Stored in mapping(bytes12 => Proposal) public proposals;.
Compact layout ensures efficient storage.
createProposal
Owner creates a new proposal with a specified voting duration.
function createProposal(bytes12 proposalID, uint32 duration) external onlyOwner- durationis in seconds and must be non-zero.
- proposalIDmust be unique.
- Emits: ProposalCreated(proposalID, duration)
- Fails with: InvalidDuration(),AlreadyVoted()
Voting System
batchVote
Owner batches votes on a proposal. Each entry represents a vote from a member ID, and whether they support the proposal.
function batchVote(
  bytes12 proposalID,
  bytes6[] calldata members,
  uint8[] calldata support
) external onlyOwner- support[i]must be either- 0or- 1.
- Array lengths must match.
- Fails with: ArrayLengthMismatch(),VotingEnded()
Voting Logic:
- Vote skipped if member has 0 tokens or already voted.
- Votes tallied into votesFororvotesAgainst.
- Tracked in memberVotes[memberID][proposalID]as signedint32.
Discretionary Funds Accrual:
if (_allotment > 0 && tb > 0) discretionaryFunds += tb * _allotment;Where _allotment = allotment and tb = total supportive token balance.
Discretionary funds are only tallied by votes for the proposal. If members do not agree with the proposal then these votes do not contribute to the overall discretionary fund allocation.
Discretionary Treasury
updateAllotment
Sets the global allotment percentage, determining ETH added to treasury per supporting token.
function updateAllotment(uint256 newAllotment) external onlyOwner- Must be non-zero, different from previous.
- Fails with: InvalidAllotment()
- Emits: AllotmentUpdated(newAllotment)
withdraw
Owner withdraws all discretionaryFunds.
function withdraw() external onlyOwner- Transfers ETH to owner using call.
- Fails with: InsufficientEther()if balance is 0 or transfer fails.
- Emits: Withdrawal(owner, amount)
Storage Layout
Mappings
mapping(bytes12 => Proposal) public proposals;
mapping(bytes6 => uint64) public memberTokens;
mapping(bytes6 => mapping(bytes12 => int32)) public memberVotes;- proposals: Proposal metadata.
- memberTokens: Member balances.
- memberVotes: Vote history and support tracking.
Errors
Custom errors to minimise gas:
- NotOwner()
- NoTokens()
- VotingEnded()
- AlreadyVoted()
- InsufficientEther()
- InvalidDuration()
- InvalidPrice()
- InvalidAllotment()
- ArrayLengthMismatch()
Events
event ProposalCreated(bytes12 indexed id, uint32 duration);
event TokensPurchased(bytes6 indexed memberID, uint32 amount);
event TokenPriceUpdated(uint256 newPrice);
event AllotmentUpdated(uint256 newAllotment);
event Withdrawal(address indexed to, uint256 amount);Events enable indexing and UI integration.
Use Cases
Community Governance
Enable member-based decisions for projects, budgeting, and prioritisation.
Batch-Based DAOs
Allow off-chain vote aggregation and on-chain batch commits, optimising cost and participation.
Controlled Fund Management
Use the allotment mechanism to safely fund treasury based on proposal support.
Low-Cost Experimental DAOs
Launch lightweight DAOs without the bloat of traditional governance frameworks.
Security Considerations
- All external write functions gated by onlyOwner.
- ETH transfers use safe low-level calls.
- Skips invalid or duplicate votes instead of reverting entire batch.
- All math operations bounded by type limits (e.g., uint48,uint64).
- Max allotmentrate enforced to limit treasury overflows.
Deployment Notes
- Use Gnosis Safe or verified multisig for deployment in production.
- Ensure tokenPriceis realistic and balances accessibility with economic stability.
- memberIDand- proposalIDshould be generated using hash truncation to prevent collisions.
- Recommended to audit the contract if used for real financial flows.
Potential Extensions
- Add IPFS or on-chain metadata for proposals.
- Add per-proposal discretionary limits.
- Add member delegation or role-based voting.
- Add token transfers or bonding curves.
- Integrate with frontends or voting UIs.
Conclusion
Kalium DAO v1 provides a lean, efficient, and functional framework for decentralised governance. With an emphasis on gas optimisation, batch operations, and clear authority boundaries, it supports real-world DAO needs without unnecessary complexity.
Its modular design and economic safety rails make it suitable for early-stage, community-led, or sustainability-oriented decentralised systems.