diff --git a/contracts/Gov.sol b/contracts/Gov.sol index d577115..3deed3d 100644 --- a/contracts/Gov.sol +++ b/contracts/Gov.sol @@ -7,6 +7,9 @@ import "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol"; import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol"; +/// @title DAO Contract +/// @notice This contract implements a voting system using OpenZeppelin's Governor framework +/// @dev Uses OpenZeppelin contracts v5.0.2 contract Gov is Governor, GovernorSettings, @@ -18,6 +21,14 @@ contract Gov is event ManifestoUpdated(string cid); + /// @notice Initializes the governance contract + /// @param _token The address of the token used for voting + /// @param _manifesto The initial CID of the manifesto + /// @param _name The name of the governance contract + /// @param _votingDelay The delay before voting starts + /// @param _votingPeriod The duration of the voting period + /// @param _votingThreshold The minimum number of votes required to create a proposal + /// @param _quorum The percentage of total supply that must participate for a vote to succeed constructor( IVotes _token, string memory _manifesto, @@ -35,20 +46,27 @@ contract Gov is manifesto = _manifesto; } + /// @notice Returns the delay before voting on a proposal may take place function votingDelay() public view override(Governor, GovernorSettings) returns (uint256) { return super.votingDelay(); } + /// @notice Returns the duration of the voting period function votingPeriod() public view override(Governor, GovernorSettings) returns (uint256) { return super.votingPeriod(); } + /// @notice Returns the quorum for a specific block number + /// @param blockNumber The block number to check the quorum for + /// @return The number of votes required for a quorum function quorum( uint256 blockNumber ) public view override(Governor, GovernorVotesQuorumFraction) returns (uint256) { return super.quorum(blockNumber); } + /// @notice Returns the proposal threshold + /// @return The minimum number of votes required to create a proposal function proposalThreshold() public view diff --git a/contracts/NFT.sol b/contracts/NFT.sol index b06e81e..3d25b5b 100644 --- a/contracts/NFT.sol +++ b/contracts/NFT.sol @@ -9,6 +9,9 @@ import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Votes.sol"; +/// @title DAO Membership NFT Contract +/// @notice This contract implements a non-transferable NFT with voting rights for DAO membership +/// @dev Extends multiple OpenZeppelin contracts to create a feature-rich NFT contract NFT is ERC721, ERC721Enumerable, @@ -20,6 +23,12 @@ contract NFT is { uint256 private _nextTokenId; + /// @notice Initializes the NFT contract + /// @param initialOwner The address of the initial owner (typically the governance contract) + /// @param _firstMembers An array of addresses for the initial DAO members + /// @param _uri The initial token URI for the NFTs + /// @param _name The name of the NFT + /// @param _symbol The symbol of the NFT constructor( address initialOwner, address[] memory _firstMembers, @@ -32,25 +41,36 @@ contract NFT is } } + /// @notice Returns the current timestamp + /// @dev This function is used for voting snapshots + /// @return The current block timestamp as a uint48 function clock() public view override returns (uint48) { return uint48(block.timestamp); } + /// @notice Describes the clock mode for voting snapshots + /// @return A string indicating that the contract uses timestamps for voting // solhint-disable-next-line func-name-mixedcase function CLOCK_MODE() public pure override returns (string memory) { return "mode=timestamp"; } - /// @notice Adds a member - /// @dev Marked `onlyOwner`: only the Gov contract can access this function - /// @param to The address of the recipient - /// @param uri The `tokenURI` of the new member's NFT metadata (should be "ipfs://") + /// @notice Adds a new member to the DAO + /// @dev Mints a new NFT to the specified address + /// @param to The address of the new member + /// @param uri The metadata URI for the new NFT function safeMint(address to, string memory uri) public onlyOwner { uint256 tokenId = _nextTokenId++; _safeMint(to, tokenId); _setTokenURI(tokenId, uri); } + /// @notice Updates the NFT ownership + /// @dev Overrides the transfer function to make NFTs non-transferable + /// @param to The recipient address + /// @param tokenId The ID of the token + /// @param auth The address authorized to make the transfer + /// @return The previous owner of the token function _update( address to, uint256 tokenId, @@ -60,6 +80,10 @@ contract NFT is return super._update(to, tokenId, auth); } + /// @notice Increases the balance of an account + /// @dev Internal function to update balances, overridden to maintain compatibility + /// @param account The account whose balance is being increased + /// @param value The amount to increase the balance by function _increaseBalance( address account, uint128 value @@ -67,27 +91,32 @@ contract NFT is super._increaseBalance(account, value); } + /// @notice Returns the token URI for a given token ID + /// @param tokenId The ID of the token + /// @return The URI string for the token's metadata function tokenURI( uint256 tokenId ) public view override(ERC721, ERC721URIStorage) returns (string memory) { return super.tokenURI(tokenId); } - /// @notice Bans a member - /// @dev Marked `onlyOwner`: only the Gov contract can access this function - /// @param tokenId The id of the NFT + /// @notice Removes a member from the DAO + /// @dev Burns the NFT associated with the member + /// @param tokenId The ID of the NFT to burn function govBurn(uint256 tokenId) public onlyOwner { _burn(tokenId); } - /// @notice Replaces the tokenId of a given NFT - /// @dev Marked `onlyOwner`: only the Gov contract can access this function - /// @param tokenId The id of the NFT - /// @param uri The new `tokenURI` for this ID (should be "ipfs://") + /// @notice Updates the metadata for a given NFT + /// @param tokenId The ID of the NFT to update + /// @param uri The new metadata URI for the NFT function setMetadata(uint256 tokenId, string memory uri) public onlyOwner { _setTokenURI(tokenId, uri); } + /// @notice Checks if the contract supports a given interface + /// @param interfaceId The interface identifier to check + /// @return bool True if the contract supports the interface, false otherwise function supportsInterface( bytes4 interfaceId ) public view override(ERC721, ERC721Enumerable, ERC721URIStorage) returns (bool) { diff --git a/hardhat.config.ts b/hardhat.config.ts index 2127abe..d69983b 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -71,8 +71,7 @@ const config: HardhatUserConfig = { optimizer: { enabled: true, runs: 200 - }, - evmVersion: "shanghai" + } } }, etherscan: {