Loading...
Loading...
contract AlexDAO { // ERC20-подобный управляющий токен string public constant name = "Alex DAO Token"; string public constant symbol = "ALEX"; uint8 public constant decimals = 18;
uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance;
// DAO-специфичные переменные address public founder; uint256 public constant PROPOSAL_THRESHOLD = 1000 * 10**18; // Минимум токенов для предложения uint256 public constant VOTING_PERIOD = 3 days; uint256 public constant EXECUTION_DELAY = 1 days;
struct Proposal { uint256 id; address proposer; string title; string description; uint256 votesFor; uint256 votesAgainst; uint256 startTime; uint256 endTime; bool executed; bool cancelled;
// Для выполнения предложений address[] targets; // Контракты для вызова uint256[] values; // ETH для отправки bytes[] calldatas; // Данные для вызова функций }
mapping(uint256 => Proposal) public proposals; mapping(uint256 => mapping(address => bool)) public hasVoted; mapping(uint256 => mapping(address => uint256)) public votingPower; // Заморозка токенов для голосования
uint256 public proposalCount; uint256 public treasury; // Казна DAO
event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value);
event ProposalCreated( uint256 indexed proposalId, address indexed proposer, string title, uint256 startTime, uint256 endTime ); event VoteCast(address indexed voter, uint256 indexed proposalId, bool support, uint256 weight); event ProposalExecuted(uint256 indexed proposalId); event ProposalCancelled(uint256 indexed proposalId);
modifier onlyDAO() { require(msg.sender == address(this), "Только DAO может выполнить это действие"); _; }
constructor() { founder = msg.sender; totalSupply = 1000000 * 10**18; // 1 миллион токенов balanceOf[founder] = totalSupply; emit Transfer(address(0), founder, totalSupply); }
// Базовые функции ERC20 function transfer(address to, uint256 amount) public returns (bool) { require(balanceOf[msg.sender] >= amount, "Недостаточно токенов");
balanceOf[msg.sender] -= amount; balanceOf[to] += amount;
emit Transfer(msg.sender, to, amount); return true; }
function approve(address spender, uint256 amount) public returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; }
function transferFrom(address from, address to, uint256 amount) public returns (bool) { require(balanceOf[from] >= amount, "Недостаточно токенов"); require(allowance[from][msg.sender] >= amount, "Недостаточно разрешений");
balanceOf[from] -= amount; balanceOf[to] += amount; allowance[from][msg.sender] -= amount;
emit Transfer(from, to, amount); return true; }
// Пополнение казны DAO receive() external payable { treasury += msg.value; }
function depositToTreasury() external payable { treasury += msg.value; }}
// Продолжение контракта AlexDAO
// Создание предложенияfunction propose( string memory title, string memory description, address[] memory targets, uint256[] memory values, bytes[] memory calldatas) public returns (uint256) { require(balanceOf[msg.sender] >= PROPOSAL_THRESHOLD, "Недостаточно токенов для создания предложения"); require(targets.length == values.length && values.length == calldatas.length, "Массивы должны быть одинаковой длины");
uint256 proposalId = proposalCount++; uint256 startTime = block.timestamp; uint256 endTime = startTime + VOTING_PERIOD;
proposals[proposalId] = Proposal({ id: proposalId, proposer: msg.sender, title: title, description: description, votesFor: 0, votesAgainst: 0, startTime: startTime, endTime: endTime, executed: false, cancelled: false, targets: targets, values: values, calldatas: calldatas });
emit ProposalCreated(proposalId, msg.sender, title, startTime, endTime); return proposalId;}
// Голосование по предложениюfunction vote(uint256 proposalId, bool support) public { Proposal storage proposal = proposals[proposalId];
require(block.timestamp >= proposal.startTime, "Голосование еще не началось"); require(block.timestamp <= proposal.endTime, "Голосование завершено"); require(!hasVoted[proposalId][msg.sender], "Уже проголосовали"); require(!proposal.executed && !proposal.cancelled, "Предложение неактивно");
uint256 weight = balanceOf[msg.sender]; require(weight > 0, "Нет права голоса");
hasVoted[proposalId][msg.sender] = true; votingPower[proposalId][msg.sender] = weight;
if (support) { proposal.votesFor += weight; } else { proposal.votesAgainst += weight; }
emit VoteCast(msg.sender, proposalId, support, weight);}
// Выполнение принятого предложенияfunction executeProposal(uint256 proposalId) public { Proposal storage proposal = proposals[proposalId];
require(block.timestamp > proposal.endTime, "Голосование еще не завершено"); require(block.timestamp <= proposal.endTime + EXECUTION_DELAY, "Время выполнения истекло"); require(!proposal.executed, "Предложение уже выполнено"); require(!proposal.cancelled, "Предложение отменено"); require(proposal.votesFor > proposal.votesAgainst, "Предложение не принято");
proposal.executed = true;
// Выполняем все действия предложения for (uint256 i = 0; i < proposal.targets.length; i++) { (bool success, ) = proposal.targets[i].call{value: proposal.values[i]}( proposal.calldatas[i] ); require(success, "Выполнение действия не удалось"); }
emit ProposalExecuted(proposalId);}
// Отмена предложения (только создатель)function cancelProposal(uint256 proposalId) public { Proposal storage proposal = proposals[proposalId];
require( msg.sender == proposal.proposer || msg.sender == founder, "Только создатель или основатель может отменить" ); require(!proposal.executed, "Нельзя отменить выполненное предложение"); require(block.timestamp <= proposal.endTime, "Голосование завершено");
proposal.cancelled = true; emit ProposalCancelled(proposalId);}
// Получение информации о предложенииfunction getProposal(uint256 proposalId) public view returns ( address proposer, string memory title, string memory description, uint256 votesFor, uint256 votesAgainst, uint256 startTime, uint256 endTime, bool executed, bool cancelled) { Proposal storage proposal = proposals[proposalId]; return ( proposal.proposer, proposal.title, proposal.description, proposal.votesFor, proposal.votesAgainst, proposal.startTime, proposal.endTime, proposal.executed, proposal.cancelled );}
// Проверка статуса предложенияfunction getProposalState(uint256 proposalId) public view returns (string memory) { Proposal storage proposal = proposals[proposalId];
if (proposal.cancelled) { return "Cancelled"; }
if (proposal.executed) { return "Executed"; }
if (block.timestamp <= proposal.endTime) { return "Active"; }
if (proposal.votesFor <= proposal.votesAgainst) { return "Defeated"; }
if (block.timestamp <= proposal.endTime + EXECUTION_DELAY) { return "Succeeded"; }
return "Expired";}
contract AlexAdvancedDAO is AlexDAO { // Делегирование голосов mapping(address => address) public delegates; // кто кому делегировал mapping(address => uint256) public delegatedVotes; // сколько голосов делегировано
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);
// Делегирование своих голосов function delegate(address delegatee) public { address currentDelegate = delegates[msg.sender]; require(delegatee != currentDelegate, "Уже делегировано этому адресу");
delegates[msg.sender] = delegatee;
uint256 delegatorBalance = balanceOf[msg.sender];
// Убираем голоса у старого делегата if (currentDelegate != address(0)) { uint256 oldVotes = delegatedVotes[currentDelegate]; delegatedVotes[currentDelegate] = oldVotes - delegatorBalance; emit DelegateVotesChanged(currentDelegate, oldVotes, delegatedVotes[currentDelegate]); }
// Добавляем голоса новому делегату if (delegatee != address(0)) { uint256 newVotes = delegatedVotes[delegatee] + delegatorBalance; delegatedVotes[delegatee] = newVotes; emit DelegateVotesChanged(delegatee, newVotes - delegatorBalance, newVotes); }
emit DelegateChanged(msg.sender, currentDelegate, delegatee); }
// Получение общей силы голоса (собственные + делегированные) function getVotingPower(address account) public view returns (uint256) { return balanceOf[account] + delegatedVotes[account]; }
// Голосование с учетом делегирования function voteWithDelegation(uint256 proposalId, bool support) public { Proposal storage proposal = proposals[proposalId];
require(block.timestamp >= proposal.startTime, "Голосование еще не началось"); require(block.timestamp <= proposal.endTime, "Голосование завершено"); require(!hasVoted[proposalId][msg.sender], "Уже проголосовали"); require(!proposal.executed && !proposal.cancelled, "Предложение неактивно");
uint256 weight = getVotingPower(msg.sender); require(weight > 0, "Нет права голоса");
hasVoted[proposalId][msg.sender] = true; votingPower[proposalId][msg.sender] = weight;
if (support) { proposal.votesFor += weight; } else { proposal.votesAgainst += weight; }
emit VoteCast(msg.sender, proposalId, support, weight); }}
contract AlexGovernanceDAO is AlexAdvancedDAO { uint256 public constant QUORUM_PERCENTAGE = 20; // 20% от общего количества токенов uint256 public constant SUPERMAJORITY_PERCENTAGE = 66; // 66% для критических решений
enum ProposalType { Standard, // Обычное предложение (простое большинство) Critical, // Критическое предложение (супермажоритет) Emergency // Экстренное предложение (короткий период голосования) }
struct GovernanceProposal { uint256 id; address proposer; string title; string description; ProposalType proposalType; uint256 votesFor; uint256 votesAgainst; uint256 startTime; uint256 endTime; bool executed; bool cancelled; address[] targets; uint256[] values; bytes[] calldatas; }
mapping(uint256 => GovernanceProposal) public governanceProposals;
// Создание предложения с типом function proposeWithType( string memory title, string memory description, ProposalType proposalType, address[] memory targets, uint256[] memory values, bytes[] memory calldatas ) public returns (uint256) { require(balanceOf[msg.sender] >= PROPOSAL_THRESHOLD, "Недостаточно токенов для создания предложения");
uint256 proposalId = proposalCount++; uint256 startTime = block.timestamp; uint256 endTime;
// Определяем период голосования в зависимости от типа if (proposalType == ProposalType.Emergency) { endTime = startTime + 1 days; // Экстренные предложения - 1 день require(balanceOf[msg.sender] >= PROPOSAL_THRESHOLD * 5, "Для экстренных предложений нужно больше токенов"); } else { endTime = startTime + VOTING_PERIOD; // Обычные - 3 дня }
governanceProposals[proposalId] = GovernanceProposal({ id: proposalId, proposer: msg.sender, title: title, description: description, proposalType: proposalType, votesFor: 0, votesAgainst: 0, startTime: startTime, endTime: endTime, executed: false, cancelled: false, targets: targets, values: values, calldatas: calldatas });
emit ProposalCreated(proposalId, msg.sender, title, startTime, endTime); return proposalId; }
// Проверка принятия предложения с учетом кворума и типа function isProposalPassed(uint256 proposalId) public view returns (bool) { GovernanceProposal storage proposal = governanceProposals[proposalId];
uint256 totalVotes = proposal.votesFor + proposal.votesAgainst; uint256 requiredQuorum = (totalSupply * QUORUM_PERCENTAGE) / 100;
// Проверяем кворум if (totalVotes < requiredQuorum) { return false; }
// Проверяем большинство в зависимости от типа предложения if (proposal.proposalType == ProposalType.Critical) { // Критические предложения требуют супермажоритет return (proposal.votesFor * 100) / totalVotes >= SUPERMAJORITY_PERCENTAGE; } else { // Обычные предложения требуют простое большинство return proposal.votesFor > proposal.votesAgainst; } }
// Выполнение предложения с проверкой кворума function executeGovernanceProposal(uint256 proposalId) public { GovernanceProposal storage proposal = governanceProposals[proposalId];
require(block.timestamp > proposal.endTime, "Голосование еще не завершено"); require(!proposal.executed, "Предложение уже выполнено"); require(!proposal.cancelled, "Предложение отменено"); require(isProposalPassed(proposalId), "Предложение не принято");
proposal.executed = true;
// Выполняем действия предложения for (uint256 i = 0; i < proposal.targets.length; i++) { (bool success, ) = proposal.targets[i].call{value: proposal.values[i]}( proposal.calldatas[i] ); require(success, "Выполнение действия не удалось"); }
emit ProposalExecuted(proposalId); }}
contract AlexDeFiDAO { // Параметры протокола, которыми управляет DAO uint256 public borrowingRate = 500; // 5% годовых (базовые пункты) uint256 public liquidationThreshold = 8000; // 80% uint256 public protocolFee = 100; // 1% address public treasury;
// Управляющий токен mapping(address => uint256) public governanceTokens; uint256 public totalGovernanceSupply;
struct ProtocolProposal { uint256 id; string title; string description; ProposalAction action; uint256 newValue; address newAddress; uint256 votesFor; uint256 votesAgainst; uint256 deadline; bool executed; address proposer; }
enum ProposalAction { ChangeBorrowingRate, ChangeLiquidationThreshold, ChangeProtocolFee, ChangeTreasury, WithdrawFromTreasury }
mapping(uint256 => ProtocolProposal) public protocolProposals; mapping(uint256 => mapping(address => bool)) public hasVotedOnProtocol; uint256 public protocolProposalCount;
event ProtocolParameterChanged(string parameter, uint256 oldValue, uint256 newValue); event TreasuryChanged(address oldTreasury, address newTreasury); event FundsWithdrawn(address to, uint256 amount);
constructor(address _treasury) { treasury = _treasury; totalGovernanceSupply = 1000000 * 10**18; governanceTokens[msg.sender] = totalGovernanceSupply; }
// Создание предложения по изменению параметров протокола function proposeProtocolChange( string memory title, string memory description, ProposalAction action, uint256 newValue, address newAddress ) public returns (uint256) { require(governanceTokens[msg.sender] >= 10000 * 10**18, "Недостаточно токенов для предложения");
uint256 proposalId = protocolProposalCount++;
protocolProposals[proposalId] = ProtocolProposal({ id: proposalId, title: title, description: description, action: action, newValue: newValue, newAddress: newAddress, votesFor: 0, votesAgainst: 0, deadline: block.timestamp + 5 days, executed: false, proposer: msg.sender });
return proposalId; }
// Голосование по изменению параметров function voteOnProtocolChange(uint256 proposalId, bool support) public { ProtocolProposal storage proposal = protocolProposals[proposalId];
require(block.timestamp <= proposal.deadline, "Голосование завершено"); require(!hasVotedOnProtocol[proposalId][msg.sender], "Уже проголосовали"); require(governanceTokens[msg.sender] > 0, "Нет права голоса");
hasVotedOnProtocol[proposalId][msg.sender] = true; uint256 weight = governanceTokens[msg.sender];
if (support) { proposal.votesFor += weight; } else { proposal.votesAgainst += weight; } }
// Выполнение принятого предложения function executeProtocolChange(uint256 proposalId) public { ProtocolProposal storage proposal = protocolProposals[proposalId];
require(block.timestamp > proposal.deadline, "Голосование не завершено"); require(!proposal.executed, "Уже выполнено"); require(proposal.votesFor > proposal.votesAgainst, "Предложение не принято");
proposal.executed = true;
if (proposal.action == ProposalAction.ChangeBorrowingRate) { uint256 oldRate = borrowingRate; borrowingRate = proposal.newValue; emit ProtocolParameterChanged("borrowingRate", oldRate, borrowingRate);
} else if (proposal.action == ProposalAction.ChangeLiquidationThreshold) { uint256 oldThreshold = liquidationThreshold; liquidationThreshold = proposal.newValue; emit ProtocolParameterChanged("liquidationThreshold", oldThreshold, liquidationThreshold);
} else if (proposal.action == ProposalAction.ChangeProtocolFee) { uint256 oldFee = protocolFee; protocolFee = proposal.newValue; emit ProtocolParameterChanged("protocolFee", oldFee, protocolFee);
} else if (proposal.action == ProposalAction.ChangeTreasury) { address oldTreasury = treasury; treasury = proposal.newAddress; emit TreasuryChanged(oldTreasury, treasury);
} else if (proposal.action == ProposalAction.WithdrawFromTreasury) { require(address(this).balance >= proposal.newValue, "Недостаточно средств"); payable(proposal.newAddress).transfer(proposal.newValue); emit FundsWithdrawn(proposal.newAddress, proposal.newValue); } }
// Пополнение казны receive() external payable {}
// Получение текущих параметров протокола function getProtocolParameters() public view returns ( uint256 _borrowingRate, uint256 _liquidationThreshold, uint256 _protocolFee, address _treasury, uint256 _treasuryBalance ) { return ( borrowingRate, liquidationThreshold, protocolFee, treasury, address(this).balance ); }}
contract AlexNFTCollectionDAO { // NFT коллекция, которой управляет DAO mapping(uint256 => address) public nftOwners; mapping(address => uint256[]) public ownedNFTs; uint256 public totalNFTs;
// Предложения по коллекции struct CollectionProposal { uint256 id; string title; string description; CollectionAction action; uint256 tokenId; address targetAddress; uint256 price; string metadataURI; uint256 votesFor; uint256 votesAgainst; uint256 deadline; bool executed; address proposer; }
enum CollectionAction { SellNFT, // Продать NFT из коллекции BuyNFT, // Купить NFT в коллекцию ChangeMetadata, // Изменить метаданные DistributeRoyalties, // Распределить роялти SetRoyaltyRate // Установить процент роялти }
mapping(uint256 => CollectionProposal) public collectionProposals; mapping(uint256 => mapping(address => bool)) public hasVotedOnCollection; uint256 public collectionProposalCount;
uint256 public royaltyRate = 500; // 5% uint256 public collectionTreasury;
event NFTSold(uint256 indexed tokenId, address buyer, uint256 price); event NFTBought(uint256 indexed tokenId, address seller, uint256 price); event RoyaltiesDistributed(uint256 totalAmount, uint256 perNFT); event MetadataUpdated(uint256 indexed tokenId, string newURI);
// Создание предложения по управлению коллекцией function proposeCollectionAction( string memory title, string memory description, CollectionAction action, uint256 tokenId, address targetAddress, uint256 price, string memory metadataURI ) public returns (uint256) { require(ownedNFTs[msg.sender].length > 0, "Только владельцы NFT могут создавать предложения");
uint256 proposalId = collectionProposalCount++;
collectionProposals[proposalId] = CollectionProposal({ id: proposalId, title: title, description: description, action: action, tokenId: tokenId, targetAddress: targetAddress, price: price, metadataURI: metadataURI, votesFor: 0, votesAgainst: 0, deadline: block.timestamp + 3 days, executed: false, proposer: msg.sender });
return proposalId; }
// Голосование владельцев NFT function voteOnCollectionProposal(uint256 proposalId, bool support) public { CollectionProposal storage proposal = collectionProposals[proposalId];
require(block.timestamp <= proposal.deadline, "Голосование завершено"); require(!hasVotedOnCollection[proposalId][msg.sender], "Уже проголосовали");
uint256 votingWeight = ownedNFTs[msg.sender].length; require(votingWeight > 0, "Нет права голоса");
hasVotedOnCollection[proposalId][msg.sender] = true;
if (support) { proposal.votesFor += votingWeight; } else { proposal.votesAgainst += votingWeight; } }
// Выполнение предложения по коллекции function executeCollectionProposal(uint256 proposalId) public { CollectionProposal storage proposal = collectionProposals[proposalId];
require(block.timestamp > proposal.deadline, "Голосование не завершено"); require(!proposal.executed, "Уже выполнено"); require(proposal.votesFor > proposal.votesAgainst, "Предложение не принято");
proposal.executed = true;
if (proposal.action == CollectionAction.SellNFT) { // Логика продажи NFT require(nftOwners[proposal.tokenId] == address(this), "NFT не принадлежит DAO"); nftOwners[proposal.tokenId] = proposal.targetAddress; collectionTreasury += proposal.price; emit NFTSold(proposal.tokenId, proposal.targetAddress, proposal.price);
} else if (proposal.action == CollectionAction.DistributeRoyalties) { // Распределение роялти между владельцами NFT require(collectionTreasury >= proposal.price, "Недостаточно средств"); uint256 perNFT = proposal.price / totalNFTs;
// В реальности здесь был бы более сложный механизм распределения emit RoyaltiesDistributed(proposal.price, perNFT); collectionTreasury -= proposal.price;
} else if (proposal.action == CollectionAction.SetRoyaltyRate) { royaltyRate = proposal.price; // Используем поле price для хранения процента } }
// Функции для управления NFT (упрощенные) function mintNFT(address to, uint256 tokenId) public { require(nftOwners[tokenId] == address(0), "NFT уже существует"); nftOwners[tokenId] = to; ownedNFTs[to].push(tokenId); totalNFTs++; }
receive() external payable { collectionTreasury += msg.value; }}
contract SecureDAO { // Временные блокировки для предотвращения flash loan атак mapping(address => uint256) public lastTokenTransfer; mapping(address => uint256) public votingPowerSnapshot; uint256 public constant VOTING_DELAY = 1 days; // Задержка между получением токенов и голосованием
// Защита от концентрации власти uint256 public constant MAX_VOTING_POWER = 1000; // Максимум 10% от общего количества токенов
// Антиспам механизмы mapping(address => uint256) public lastProposalTime; uint256 public constant PROPOSAL_COOLDOWN = 1 days;
// Система репутации mapping(address => uint256) public reputation; mapping(address => uint256) public successfulProposals; mapping(address => uint256) public totalProposals;
event SecurityViolationDetected(address indexed account, string violation); event ReputationUpdated(address indexed account, uint256 newReputation);
modifier onlyAfterDelay() { require( block.timestamp >= lastTokenTransfer[msg.sender] + VOTING_DELAY, "Необходимо подождать после получения токенов" ); _; }
modifier respectsCooldown() { require( block.timestamp >= lastProposalTime[msg.sender] + PROPOSAL_COOLDOWN, "Слишком частые предложения" ); lastProposalTime[msg.sender] = block.timestamp; _; }
// Безопасное голосование с проверками function secureVote(uint256 proposalId, bool support) public onlyAfterDelay { // Используем снимок баланса на момент создания предложения uint256 votingPower = votingPowerSnapshot[msg.sender];
// Ограничиваем максимальную силу голоса if (votingPower > (totalSupply * MAX_VOTING_POWER) / 10000) { votingPower = (totalSupply * MAX_VOTING_POWER) / 10000; emit SecurityViolationDetected(msg.sender, "Превышение максимальной силы голоса"); }
// Остальная логика голосования... }
// Создание снимка силы голоса при создании предложения function createSnapshotForProposal() internal { // Сохраняем текущую силу голоса всех участников // В реальности это было бы более сложно реализовано }
// Система репутации function updateReputation(address account, bool proposalSucceeded) internal { totalProposals[account]++;
if (proposalSucceeded) { successfulProposals[account]++; reputation[account] += 10; } else { if (reputation[account] >= 5) { reputation[account] -= 5; } }
emit ReputationUpdated(account, reputation[account]); }
// Проверка права создания предложения с учетом репутации function canCreateProposal(address account) public view returns (bool) { // Новые пользователи могут создать 1 предложение if (totalProposals[account] == 0) { return true; }
// Проверяем процент успешных предложений uint256 successRate = (successfulProposals[account] * 100) / totalProposals[account];
// Если процент успеха меньше 20% и репутация низкая, блокируем if (successRate < 20 && reputation[account] < 50) { return false; }
return true; }}
contract MultiSigDAO { address[] public guardians; // Хранители DAO uint256 public constant REQUIRED_SIGNATURES = 3; // Минимум подписей для критических операций
struct CriticalOperation { bytes32 operationHash; address[] signers; bool executed; uint256 deadline; }
mapping(bytes32 => CriticalOperation) public criticalOperations; mapping(bytes32 => mapping(address => bool)) public hasSigned;
event CriticalOperationProposed(bytes32 indexed operationHash, uint256 deadline); event CriticalOperationSigned(bytes32 indexed operationHash, address indexed signer); event CriticalOperationExecuted(bytes32 indexed operationHash);
modifier onlyGuardian() { bool isGuardian = false; for (uint256 i = 0; i < guardians.length; i++) { if (guardians[i] == msg.sender) { isGuardian = true; break; } } require(isGuardian, "Только хранители могут выполнить это действие"); _; }
constructor(address[] memory _guardians) { require(_guardians.length >= REQUIRED_SIGNATURES, "Недостаточно хранителей"); guardians = _guardians; }
// Предложение критической операции function proposeCriticalOperation( address target, uint256 value, bytes memory data ) public onlyGuardian returns (bytes32) { bytes32 operationHash = keccak256(abi.encodePacked(target, value, data, block.timestamp));
criticalOperations[operationHash] = CriticalOperation({ operationHash: operationHash, signers: new address[](0), executed: false, deadline: block.timestamp + 7 days });
// Автоматически подписываем от имени предлагающего _signOperation(operationHash, msg.sender);
emit CriticalOperationProposed(operationHash, block.timestamp + 7 days); return operationHash; }
// Подпись критической операции function signCriticalOperation(bytes32 operationHash) public onlyGuardian { require(!criticalOperations[operationHash].executed, "Операция уже выполнена"); require(block.timestamp <= criticalOperations[operationHash].deadline, "Время подписи истекло"); require(!hasSigned[operationHash][msg.sender], "Уже подписано");
_signOperation(operationHash, msg.sender); }
function _signOperation(bytes32 operationHash, address signer) internal { hasSigned[operationHash][signer] = true; criticalOperations[operationHash].signers.push(signer);
emit CriticalOperationSigned(operationHash, signer); }
// Выполнение критической операции function executeCriticalOperation( bytes32 operationHash, address target, uint256 value, bytes memory data ) public { CriticalOperation storage operation = criticalOperations[operationHash];
require(!operation.executed, "Операция уже выполнена"); require(operation.signers.length >= REQUIRED_SIGNATURES, "Недостаточно подписей"); require(block.timestamp <= operation.deadline, "Время выполнения истекло");
// Проверяем, что хеш соответствует параметрам bytes32 expectedHash = keccak256(abi.encodePacked(target, value, data, operation.deadline - 7 days)); require(expectedHash == operationHash, "Неверные параметры операции");
operation.executed = true;
(bool success, ) = target.call{value: value}(data); require(success, "Выполнение операции не удалось");
emit CriticalOperationExecuted(operationHash); }}
contract OracleDAO { // Интерфейс для получения внешних данных interface IPriceOracle { function getPrice(string memory symbol) external view returns (uint256); }
IPriceOracle public priceOracle;
struct DataDrivenProposal { uint256 id; string title; string description; string priceSymbol; // Токен для отслеживания цены uint256 triggerPrice; // Цена срабатывания bool triggerAbove; // true = выше цены, false = ниже цены address[] targets; uint256[] values; bytes[] calldatas; bool executed; uint256 createdAt; address proposer; }
mapping(uint256 => DataDrivenProposal) public dataDrivenProposals; uint256 public dataDrivenProposalCount;
event DataDrivenProposalCreated(uint256 indexed proposalId, string symbol, uint256 triggerPrice); event DataDrivenProposalTriggered(uint256 indexed proposalId, uint256 currentPrice);
// Создание предложения, зависящего от данных function createDataDrivenProposal( string memory title, string memory description, string memory priceSymbol, uint256 triggerPrice, bool triggerAbove, address[] memory targets, uint256[] memory values, bytes[] memory calldatas ) public returns (uint256) { uint256 proposalId = dataDrivenProposalCount++;
dataDrivenProposals[proposalId] = DataDrivenProposal({ id: proposalId, title: title, description: description, priceSymbol: priceSymbol, triggerPrice: triggerPrice, triggerAbove: triggerAbove, targets: targets, values: values, calldatas: calldatas, executed: false, createdAt: block.timestamp, proposer: msg.sender });
emit DataDrivenProposalCreated(proposalId, priceSymbol, triggerPrice); return proposalId; }
// Проверка и выполнение предложения на основе данных function checkAndExecuteDataDrivenProposal(uint256 proposalId) public { DataDrivenProposal storage proposal = dataDrivenProposals[proposalId];
require(!proposal.executed, "Предложение уже выполнено"); require(block.timestamp >= proposal.createdAt + 1 hours, "Слишком рано для выполнения");
uint256 currentPrice = priceOracle.getPrice(proposal.priceSymbol);
bool shouldExecute = false; if (proposal.triggerAbove) { shouldExecute = currentPrice >= proposal.triggerPrice; } else { shouldExecute = currentPrice <= proposal.triggerPrice; }
require(shouldExecute, "Условие не выполнено");
proposal.executed = true;
// Выполняем действия for (uint256 i = 0; i < proposal.targets.length; i++) { (bool success, ) = proposal.targets[i].call{value: proposal.values[i]}( proposal.calldatas[i] ); require(success, "Выполнение действия не удалось"); }
emit DataDrivenProposalTriggered(proposalId, currentPrice); }}
Термин | Определение | Пример использования |
---|---|---|
DAO | Decentralized Autonomous Organization - децентрализованная автономная организация | Управление DeFi протоколом через голосование |
Governance Token | Управляющий токен, дающий право голоса в DAO | Токены UNI для управления Uniswap |
Proposal | Предложение для голосования в DAO | Изменение процентной ставки в протоколе |
Quorum | Минимальное количество голосов для валидности решения | 20% от всех токенов должны участвовать в голосовании |
Supermajority | Квалифицированное большинство для критических решений | 66% голосов для изменения основных параметров |
Delegation | Делегирование права голоса другому участнику | Передача голосов эксперту в области |
Treasury | Казна DAO с коллективно управляемыми средствами | Фонд для финансирования разработки |
Voting Power | Сила голоса участника DAO | Количество токенов определяет вес голоса |
Execution Delay | Задержка между принятием решения и его выполнением | 1 день на отмену ошибочного решения |
Guardian | Хранитель DAO с правом вето на критические операции | Мультисиг кошелек для защиты от атак |
Flash Loan Attack | Атака с использованием мгновенных займов для манипуляции голосованием | Временное получение токенов для влияния на голос |
Governance Mining | Распределение управляющих токенов за участие в протоколе | Получение токенов за использование DeFi платформы |