// SPDX-License-Identifier: GPL-3.0-or-later // This file is part of the http://github.com/aaronbloomfield/ccc repository, // and is released under the GPL 3.0 license. import "./IERC165.sol"; pragma solidity ^0.8.24; // This file is heavily adapted from the DAO interface at // https://github.com/blockchainsllc/DAO/blob/develop/DAO.sol interface IDAO is IERC165 { //------------------------------------------------------------ // A struct to hold all of our proposal data struct Proposal { address recipient; // The address where the `amount` will go to if the proposal is accepted uint amount; // The amount to transfer to `recipient` if the proposal is accepted. string description; // The amount to transfer to `recipient` if the proposal is accepted. uint votingDeadline; // A UNIX timestamp, denoting the end of the voting period bool open; // True if the proposal's votes have yet to be counted, otherwise False bool proposalPassed; // True if the votes have been counted, and the majority said yes uint yea; // Number of Tokens in favor of the proposal; updated upon each yea vote uint nay; // Number of Tokens opposed to the proposal; updated upon each nay vote address creator; // Address of the shareholder who created the proposal } //------------------------------------------------------------ // These are all just public variables; some of which are set in the // constructor and never changed // Obtain a given proposal. If one lists out the individual fields of // the Proposal struct, then one can just have this be a public mapping // (otherwise you run into problems with "Proposal memory" // versus "Proposal storage" // // @param i The proposal ID to obtain // @return The proposal for that ID function proposals(uint i) external view returns (address,uint,string memory,uint,bool,bool,uint,uint,address); // The minimum debate period that a generic proposal can have, in seconds; // this can be set to any reasonable for testing, but should be set to 10 // minutes (600 seconds) for final submission. This can be a constant. // // @return The minimum debating period in seconds function minProposalDebatePeriod() external view returns (uint); // NFT token contract address // // @return The contract address of the NFTManager (ERC-721 contract) function tokens() external view returns (address); // A string indicating the purpose of this DAO -- be creative! This can // be a constant. // // @return A string describing the purpose of this DAO function purpose() external view returns (string memory); // Simple mapping to check if a shareholder has voted for it // // @param a The address of a member who voted // @param pid The proposal ID of a proposal // @return Whether the passed member voted yes for the passed proposal function votedYes(address a, uint pid) external view returns (bool); // Simple mapping to check if a shareholder has voted against it // // @param a The address of a member who voted // @param pid The proposal ID of a proposal // @return Whether the passed member voted no for the passed proposal function votedNo(address a, uint pid) external view returns (bool); // The total number of proposals ever created // // @return The total number of proposals ever created function numberOfProposals() external view returns (uint); // A string that states how one joins the DAO -- perhaps contacting the // deployer, perhaps some other secret means. Make this something // creative! // // @return A description of what one has to do to join this DAO function howToJoin() external view returns (string memory); // This is the amount of ether (in wei) that has been reserved for // proposals. This is increased by the proposal amount when a new // proposal is created, thus "reserving" those ether from being spent on // another proposal while this one is still being voted upon. If a // proposal succeeds, then the proposal amount is paid out. In either // case, once the voting period for the proposal ends, this amount is // reduced by the proposal amount. // // @return The amount of ether, in wei, reserved for proposals function reservedEther() external view returns (uint); // Who is the curator (owner / deployer) of this contract? // // @return The curator (deployer) of this contract function curator() external view returns (address); //------------------------------------------------------------ // Functions to implement // This allows the function to receive ether without having a payable // function -- it doesn't have to have any code in its body, but it does // have to be present. receive() external payable; // `msg.sender` creates a proposal to send `_amount` Wei to `_recipient` // with the transaction data `_transactionData`. This can only be called // by a member of the DAO, and should revert otherwise. // // @param recipient Address of the recipient of the proposed transaction // @param amount Amount of wei to be sent with the proposed transaction // @param description String describing the proposal // @param debatingPeriod Time used for debating a proposal, at least // `minProposalDebatePeriod()` seconds long. Note that the // provided parameter can *equal* the `minProposalDebatePeriod()` // as well. // @return The proposal ID function newProposal(address recipient, uint amount, string memory description, uint debatingPeriod) external payable returns (uint); // Vote on proposal `_proposalID` with `_supportsProposal`. This can only // be called by a member of the DAO, and should revert otherwise. // // @param proposalID The proposal ID // @param supportsProposal true/false as to whether in support of the // proposal function vote(uint proposalID, bool supportsProposal) external; // Checks whether proposal `_proposalID` with transaction data // `_transactionData` has been voted for or rejected, and transfers the // ETH in the case it has been voted for. This can only be called by a // member of the DAO, and should revert otherwise. It also reverts if // the proposal cannot be closed (time is not up, etc.). // // @param proposalID The proposal ID function closeProposal(uint proposalID) external; // Returns true if the passed address is a member of this DAO, false // otherwise. This likely has to call the NFTManager, so it's not just a // public variable. For this assignment, this should be callable by both // members and non-members. // // @param who An account address // @return A bool as to whether the passed address is a member of this DAO function isMember(address who) external view returns (bool); // Adds the passed member. For this assignment, any current member of the // DAO can add members. Membership is indicated by an NFT token, so one // must be transferred to this member as part of this call. This can only // be called by a member of the DAO, and should revert otherwise. // @param who The new member to add // // @param who An account address to have join the DAO function addMember(address who) external; // This is how one requests to join the DAO. Presumably they called // howToJoin(), and fulfilled any requirement(s) therein. In a real // application, this would put them into a list for the owner(s) to // approve or deny. For our uses, this will automatically allow the // caller (`msg.sender`) to be a member of the DAO. This functionality // is for grading purposes. This function should revert if the caller is // already a member. function requestMembership() external; // also supportsInterface() from IERC165; it should support two // interfaces (IERC165 and IDAO) //------------------------------------------------------------ // Events to emit // Called whenever newProposal() successfully completes // @param proposalID The proposal ID that was just created // // @param recipient The recipient address that will receive the ether if // the proposal is successful // @param amount The amount of wei that the recipient will receive // @param description A short textual description of the proposal event NewProposal(uint indexed proposalID, address indexed recipient, uint indexed amount, string description); // Called whenever a proposal is voted upon // // @param proposalID Which proposal was voted upon // @param position Whether they were in support of the proposal or not // @param voter Who voted event Voted(uint indexed proposalID, bool indexed position, address indexed voter); // Called whenever a proposal is successfully closed via `closeProposal()` // // @param proposalID The proposal that was closed // @param result Whether the proposal was successful or not event ProposalClosed(uint indexed proposalID, bool indexed result); }