Розробка мультисиг-управління казначейством DAO

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Розробка мультисиг-управління казначейством DAO
Складний
~1-2 тижні
Часті запитання

Напрямки блокчейн-розробки

Етапи блокчейн-розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1306
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1218
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    920
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1147
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    610
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    885

Доступ до членів DAO через NFT

Членство в NFT — альтернатива управлінню зважено на токени. Замість "1 токен = 1 голос" це "1 NFT = 1 голос" або "власність NFT = доступ." Це вирішує частину проблем плутократії: великий емітент не домінує автоматично. MolochDAO, Guild.xyz, Friends With Benefits — приклади систем, де членство визначається NFT або whitelist, не просто балансом токенів.

Технічно завдання розбивається на два: сам контракт членства NFT й система контролю доступу, яка перевіряє власність NFT для захищених операцій.

Контракт членства NFT

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";

contract DAOMembershipNFT is ERC721, AccessControl {
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

    // Soulbound: NFT неможна передати
    bool public isSoulbound;

    // Merkle root для whitelist мінтингу
    bytes32 public merkleRoot;

    uint256 private _tokenIdCounter;
    uint256 public maxSupply;

    // Система рівнів: 1 = Член, 2 = Core, 3 = Засновник
    mapping(uint256 => uint8) public memberTier;
    mapping(address => bool) public hasMinted;

    event MemberAdded(address indexed member, uint256 tokenId, uint8 tier);
    event MemberRevoked(uint256 indexed tokenId);

    constructor(
        string memory name,
        string memory symbol,
        uint256 _maxSupply,
        bool _soulbound
    ) ERC721(name, symbol) {
        maxSupply = _maxSupply;
        isSoulbound = _soulbound;
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
    }

    // Мінтинг через Merkle proof (для запуску whitelist)
    function mintWithProof(
        bytes32[] calldata proof,
        uint8 tier
    ) external {
        require(!hasMinted[msg.sender], "Already minted");
        require(_tokenIdCounter < maxSupply, "Max supply reached");

        bytes32 leaf = keccak256(abi.encodePacked(msg.sender, tier));
        require(MerkleProof.verify(proof, merkleRoot, leaf), "Invalid proof");

        hasMinted[msg.sender] = true;
        _mintMember(msg.sender, tier);
    }

    // Мінтинг через рішення управління
    function mintByGovernance(
        address to,
        uint8 tier
    ) external onlyRole(MINTER_ROLE) {
        require(!hasMinted[to], "Already has membership");
        _mintMember(to, tier);
    }

    function _mintMember(address to, uint8 tier) internal {
        uint256 tokenId = ++_tokenIdCounter;
        memberTier[tokenId] = tier;
        _safeMint(to, tokenId);
        emit MemberAdded(to, tokenId, tier);
    }

    // Soulbound: блокування передач
    function _beforeTokenTransfer(
        address from, address to, uint256 tokenId, uint256 batchSize
    ) internal override {
        super._beforeTokenTransfer(from, to, tokenId, batchSize);
        if (isSoulbound && from != address(0) && to != address(0)) {
            revert("Soulbound: non-transferable");
        }
    }

    // Відкликати членство через управління (burn)
    function revoke(uint256 tokenId) external onlyRole(MINTER_ROLE) {
        address owner = ownerOf(tokenId);
        hasMinted[owner] = false;
        _burn(tokenId);
        emit MemberRevoked(tokenId);
    }
}

Soulbound vs передаваємі NFT

Soulbound (ERC-5192) — NFT неможна продати чи передати. Членство пов'язане з особистістю, не капіталом. Підходить для DAO, де важлива справжня особистість учасника (контрибьютор DAO, професійні гільдії). Недолік: якщо ключ втрачено — немає способу передати членство без голосування управління.

Передаваємі членства NFT — працюють як коллекційні токени доступу (наприклад, Nouns DAO). Можна продати місце в DAO. Більш ліквідні; створює ринкову ціну для членства. Ризик: спекулятивний ринок може спотворити склад DAO.

Система рівнів

Простого "так/ні" недостатньо для складних DAO. Рівні гнучкості:

Рівень Назва Права Отримання
1 Observer Читати закриті обговорення Whitelist mint
2 Член Голосування, пропозиції Активність 30+ днів
3 Core Комітет грантів, veto Голосування спільноти
4 Засновник Мультисиг казни Тільки команда засновників

Підвищення рівня через пропозицію управління: будь-який член Tier 2 може номінувати іншого для Tier 3. Governor голосує; якщо пройшла, MINTER_ROLE мінтує оновлення.

On-chain верифікація власності

Контроль доступу до функцій DAO через перевірку балансу:

contract DAOGovernanceWithNFT {
    DAOMembershipNFT public membershipNFT;

    modifier onlyMember() {
        require(membershipNFT.balanceOf(msg.sender) > 0, "Not a member");
        _;
    }

    modifier onlyTier(uint8 minTier) {
        uint256 balance = membershipNFT.balanceOf(msg.sender);
        require(balance > 0, "Not a member");

        // Знайти найвищий рівень члена
        uint8 highestTier = _getHighestTier(msg.sender);
        require(highestTier >= minTier, "Insufficient tier");
        _;
    }

    function createProposal(...) external onlyMember() { ... }
    function accessTreasury(...) external onlyTier(3) { ... }

    function _getHighestTier(address member) internal view returns (uint8) {
        uint256 balance = membershipNFT.balanceOf(member);
        uint8 highest = 0;
        // Для малих DAO (< 1000 членів) можна ітерувати
        for (uint256 i = 0; i < balance; i++) {
            uint256 tokenId = membershipNFT.tokenOfOwnerByIndex(member, i);
            uint8 tier = membershipNFT.memberTier(tokenId);
            if (tier > highest) highest = tier;
        }
        return highest;
    }
}

Для DAO з тисячами членів ітерація в on-chain функції — проблема. Альтернатива: зберігати address => uint8 tier маппінг у контракті, оновлений при mint/burn.

Off-chain верифікація через підпис

Для доступу до закритих каналів Discord, внутрішніх сайтів або off-chain ресурсів — верифікація через підпис гаманця без транзакції:

// Frontend: користувач підписує повідомлення
const message = `Verify DAO membership\nTimestamp: ${Date.now()}\nAddress: ${address}`;
const signature = await signer.signMessage(message);

// Backend: перевірити підпис + власність
async function verifyMembership(address: string, signature: string): Promise<boolean> {
  // Відновити адресу з підпису
  const recovered = ethers.verifyMessage(message, signature);
  if (recovered.toLowerCase() !== address.toLowerCase()) return false;

  // Перевірити баланс NFT через RPC
  const nft = new ethers.Contract(NFT_ADDRESS, ABI, provider);
  const balance = await nft.balanceOf(address);
  return balance.gt(0);
}

Цей паттерн використовується Guild.xyz та Collab.Land для Discord гейтингу. Користувач не платить газ, просто підписує — й отримує роль Discord при наявності NFT.

Графік розробки

Дизайн (3-5 днів). Структура рівнів, soulbound vs передаваємий, механіка запуску (Merkle whitelist, публічний mint, тільки управління), інтеграція з існуючим Governor або новий.

Розробка контрактів (1,5-2 тижні). Членство NFT + інтеграція управління + тестування.

Off-chain інтеграція (1 тиждень). Верифікація бекенду, бот Discord/Telegram через Collab.Land або користувацький.

Аудит (1 тиждень). Контракти NFT з контролем доступу вимагають аудиту, особливо логіки відкликання.

Графік і вартість — після деталізації вимог.