Skip to main content
The Agora DAO smart contract system provides a complete infrastructure for creating and managing decentralized autonomous organizations on Ethereum and EVM-compatible networks.

Contract architecture

The system is built around a factory pattern with two core contracts:
  • AgoraDaoFactory - Factory contract for deploying new DAO instances
  • AgoraDao - Individual DAO contract with role-based access control
Both contracts leverage modular inheritance to separate concerns:
  • Rol - Abstract contract handling role-based permissions
  • Validation - Input validation logic for DAO creation

Key contracts

AgoraDaoFactory

The factory contract (contracts/AgoraDaoFactory.sol:15) manages the creation and registry of all DAOs in the system. Key features:
  • Creates new DAO instances via the factory pattern
  • Maintains a global registry of all DAOs
  • Tracks DAO categories (Service, Governance, Social Impact, Energy)
  • Counts unique users across the platform
  • Inherits from OpenZeppelin’s Ownable for admin controls
contract AgoraDaoFactory is Ownable, Validation {
    struct Dao {
        uint256 daoID;
        address creator;
        address daoAddress;
        string name;
        string description;
        string category;
        string imageURI;
        uint256 creationTimestamp;
    }

    uint256 public userCounter;
    uint256 public daoCounter;
    Dao[] public allDaos;
}

AgoraDao

Individual DAO contract (contracts/AgoraDao.sol:17) that manages members and roles. Key features:
  • Role-based access control via the Rol abstract contract
  • User membership management
  • Integration with parent factory contract
  • Built on OpenZeppelin’s AccessControl
contract AgoraDao is Rol {
    address public fabric;
    uint256 public daoID;
    uint256 public userCounter;

    constructor(address _fabric, address _creator) {
        fabric = _fabric;
        _grantRole(DEFAULT_ADMIN_ROLE, _creator);
        userCounter++;
    }
}

Rol (Role management)

Abstract contract (contracts/AgoraDao/Rol.sol:6) providing comprehensive role-based access control. Available roles:
  • DEFAULT_ADMIN_ROLE - Full administrative privileges (DAO creator)
  • AUDITOR_ROLE - Can assign roles (except admin)
  • TASK_MANAGER_ROLE - Manages tasks (future functionality)
  • PROPOSAL_MANAGER_ROLE - Manages proposals (future functionality)
  • USER_ROLE - Standard DAO member
abstract contract Rol is AccessControl {
    bytes32 internal constant AUDITOR_ROLE = keccak256("AUDITOR_ROLE");
    bytes32 internal constant TASK_MANAGER_ROLE = keccak256("TASK_MANAGER_ROLE");
    bytes32 internal constant PROPOSAL_MANAGER_ROLE = keccak256("PROPOSAL_MANAGER_ROLE");
    bytes32 internal constant USER_ROLE = keccak256("USER_ROLE");
}

Validation

Abstract contract (contracts/AgoraDaoFactory/Validation.sol:4) that validates DAO creation parameters. Validation rules:
  • Name: 1-50 characters
  • Description: 1-500 characters
  • Category ID must be valid
Validation logic
abstract contract Validation {
    function _createDao(
        string memory _name,
        string memory _description,
        uint256 _categoryID,
        string[] memory _daoCategories
    ) internal virtual {
        require(bytes(_name).length > 0, "Dao name must not be empty");
        require(bytes(_name).length <= 50, "The name of the DAO is very long");
        require(bytes(_description).length > 0, "DAO description must not be empty");
        require(bytes(_description).length <= 500, "The description of the DAO is very long");
        require(_categoryID < _daoCategories.length, "Invalid category ID.");
    }
}

OpenZeppelin dependencies

The contracts leverage battle-tested OpenZeppelin libraries:
  • AccessControl - Role-based permission system used in Rol.sol
  • Ownable - Single owner pattern used in AgoraDaoFactory.sol
These dependencies are specified in package.json:
"dependencies": {
  "@openzeppelin/contracts": "^5.0.2"
}

Security features

Every privileged operation requires specific role permissions. Admins cannot assign roles to themselves, and only admins can assign auditor roles.
All user inputs are validated for length and format before storage, preventing excessive gas costs and invalid data.
Follows checks-effects-interactions pattern. State changes occur before external calls.
New DAOs are deployed via a trusted factory, ensuring consistent initialization and proper tracking.
Built on audited, industry-standard contracts for ownership and access control.

Events

Contracts emit events for important state changes: AgoraDaoFactory:
  • DaoCreated(uint256 indexed daoID, address indexed creator, string indexed name)
AgoraDao:
  • UserJoined(address indexed user, uint256 userID)
Rol:
  • RoleRegistered(bytes32 indexed role, address indexed user, address indexed executor)
  • RoleDeleted(bytes32 indexed role, address indexed user, address indexed executor)

Next steps

Architecture

Deep dive into contract relationships and inheritance

Deployment

Learn how to deploy and verify contracts

Build docs developers (and LLMs) love