// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; contract NGovernance is Ownable, ReentrancyGuard { IERC20 public navisToken; struct Proposal { uint256 proposalId; string title; uint256 votingEndTime; uint256 forVotes; uint256 againstVotes; bool executed; mapping(address => bool) hasVoted; } mapping(uint256 => Proposal) public proposals; uint256 public totalProposals; uint256 public votingDuration = 7 days; event ProposalCreated(uint256 proposalId, string title, uint256 votingEndTime); event VoteCasted(address indexed voter, uint256 proposalId, bool support); event ProposalExecuted(uint256 proposalId); constructor(address _navisToken) { navisToken = IERC20(_navisToken); } function createProposal(string memory _title) external nonReentrant { uint256 proposalId = totalProposals + 1; uint256 votingEndTime = block.timestamp + votingDuration; proposals[proposalId] = Proposal({ proposalId: proposalId, title: _title, votingEndTime: votingEndTime, forVotes: 0, againstVotes: 0, executed: false }); totalProposals++; emit ProposalCreated(proposalId, _title, votingEndTime); } function castVote(uint256 _proposalId, bool _support) external nonReentrant { Proposal storage proposal = proposals[_proposalId]; require(proposal.proposalId != 0, "Invalid proposalId"); require(block.timestamp < proposal.votingEndTime, "Voting has ended"); require(!proposal.hasVoted[msg.sender], "Already voted"); if (_support) { proposal.forVotes = proposal.forVotes + navisToken.balanceOf(msg.sender); } else { proposal.againstVotes = proposal.againstVotes + navisToken.balanceOf(msg.sender); } proposal.hasVoted[msg.sender] = true; emit VoteCasted(msg.sender, _proposalId, _support); } function executeProposal(uint256 _proposalId) external onlyOwner nonReentrant { Proposal storage proposal = proposals[_proposalId]; require(proposal.proposalId != 0, "Invalid proposalId"); require(block.timestamp >= proposal.votingEndTime, "Voting has not ended"); require(!proposal.executed, "Proposal already executed"); // Implement your logic to execute the proposal // This can include calling specific functions or modifying state variables proposal.executed = true; emit ProposalExecuted(_proposalId); } function setVotingDuration(uint256 _duration) external onlyOwner { // Allow the owner to adjust the voting duration votingDuration = _duration; } }