← Return to Resources Technical

Kalium DAO v1 Smart Contract: Technical Documentation

by Kalium DAO Administration • Published: 6/8/2025

Version: 1.0

View Original Document →

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 int32 values.
  • 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 payable

Mechanics:

  • 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
  • duration is in seconds and must be non-zero.
  • proposalID must 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 0 or 1.
  • Array lengths must match.
  • Fails with: ArrayLengthMismatch(), VotingEnded()

Voting Logic:

  • Vote skipped if member has 0 tokens or already voted.
  • Votes tallied into votesFor or votesAgainst.
  • Tracked in memberVotes[memberID][proposalID] as signed int32.

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 allotment rate enforced to limit treasury overflows.

Deployment Notes

  • Use Gnosis Safe or verified multisig for deployment in production.
  • Ensure tokenPrice is realistic and balances accessibility with economic stability.
  • memberID and proposalID should 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.