pragma solidity ^0.8.0;


contract TheDAO {
    struct Proposal {
        address proposer;
        uint256 endTime;
        string description;
        uint256 voteCount;
        bool executed;
    }

    mapping(uint256 => Proposal) public proposals;
    uint256 public proposalCount;
    IERC721 public nftContract;
    address public admin;
    uint256 public votingPeriod;

    struct Ticker {
        string name;
        uint256 multiplier;
    }

    mapping(address => Ticker) public tickerMultipliers;

    event ProposalCreated(address indexed proposer, uint256 proposalId);

    constructor() {
        admin = msg.sender;
        tickerMultipliers[address(0)] = Ticker("milady", 10);
    }

    modifier onlyAdmin() {
        require(msg.sender == admin, "Not admin");
        _;
    }

    function setNFTContract(address _nftContract) external onlyAdmin {
        nftContract = IERC721(_nftContract);
    }

    function setVotingPeriod(uint256 _votingPeriod) external onlyAdmin {
        votingPeriod = _votingPeriod;
    }

    function setMultiplier(address _nftHolder, string memory _name, uint256 _multiplier) external onlyAdmin {
        tickerMultipliers[_nftHolder] = Ticker(_name, _multiplier);
    }

    function createProposal(string calldata _description) external {
        require(address(nftContract) != address(0), "NFT contract not set");
        require(votingPeriod > 0, "Voting period not set");

        proposalCount += 1;
        proposals[proposalCount] = Proposal(
            msg.sender,
            block.timestamp + votingPeriod,
            _description,
            0,
            false
        );
        emit ProposalCreated(msg.sender, proposalCount);
    }

    function vote(uint256 proposalId) external {
        require(address(nftContract) != address(0), "NFT contract not set");

        Proposal storage proposal = proposals[proposalId];
        require(proposal.endTime > block.timestamp, "Voting period over");
        require(nftContract.ownerOf(uint256(uint160(msg.sender))) == msg.sender, "Must hold NFT to vote");

        Ticker memory voterTicker = tickerMultipliers[msg.sender];
        uint256 votePower = voterTicker.multiplier;
        proposal.voteCount += votePower;
    }

    function execute(uint256 proposalId, uint256 quorum) external {
        require(votingPeriod > 0, "Voting period not set");

        Proposal storage proposal = proposals[proposalId];
        require(proposal.endTime <= block.timestamp, "Voting period ongoing");
        require(proposal.proposer != address(0), "Already executed");
        require(proposal.voteCount >= quorum, "Not enough votes");

        // Execute proposal
        // Implement custom logic based on proposal
        proposal.executed = true;
    }

    function setAdmin(address _admin) external onlyAdmin {
        admin = _admin;
    }
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"proposer","type":"address"},{"indexed":false,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalCreated","type":"event"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_description","type":"string"}],"name":"createProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint256","name":"quorum","type":"uint256"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nftContract","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"proposals","outputs":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"string","name":"description","type":"string"},{"internalType":"uint256","name":"voteCount","type":"uint256"},{"internalType":"bool","name":"executed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftHolder","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"uint256","name":"_multiplier","type":"uint256"}],"name":"setMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftContract","type":"address"}],"name":"setNFTContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_votingPeriod","type":"uint256"}],"name":"setVotingPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tickerMultipliers","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"multiplier","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"vote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"votingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]