// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract e2WDAO is Ownable { // Token contracts IERC20 public e2WToken; IERC20 public e2XToken; IERC20 public USDeToken; mapping(address => bool) public allowedTokens; // Addresses of other contracts address[] public contracts; // Token allocation variables mapping(uint256 => uint256) public tokenAllocations; // Mapping for token allocations for different rounds uint256 public rewardAllocation; // Tokens allocated for rewards uint256 public biddingAllocation; // Tokens allocated for bidding address public rewardAddress; // Reward wallet address // Token price constants mapping(uint256 => uint256) public tokenPrices; // Mapping for token prices for different rounds // Total supply of e2W tokens uint256 public totalSupply; // Token holders' balances mapping(address => uint256) public balances; // Voting details struct Voting { uint256 startTime; uint256 endTime; address initiator; string referenceNumber; mapping(address => bool) votes; } uint256 public votingDuration; // Duration of each voting process uint256 public votingThreshold; // Threshold for passing a resolution (in percentage) mapping(string => Voting) public votings; // Mapping of reference numbers to voting details // Constructor constructor( address _e2WToken, address _e2XToken, address _USDeToken, address _initialOwner // Added initialOwner parameter ) Ownable(_initialOwner) { e2WToken = IERC20(_e2WToken); e2XToken = IERC20(_e2XToken); USDeToken = IERC20(_USDeToken); totalSupply = 1000000; votingDuration = 1 days; // Voting duration set to 1 day by default votingThreshold = 10; // Voting threshold set to 10% by default // Initially, only e2W token is allowed allowedTokens[_e2WToken] = true; allowedTokens[_e2XToken] = true; } // Function to add contract address function addContract(address _contract) external onlyOwner { contracts.push(_contract); } // Function to remove contract address function removeContract(uint256 _index) external onlyOwner { require(_index < contracts.length, "Index out of bounds"); contracts[_index] = contracts[contracts.length - 1]; contracts.pop(); } // Function to update token allocation function updateTokenAllocation(uint256 _round, uint256 _amount) external onlyOwner { tokenAllocations[_round] = _amount; } // Function to update token price function updateTokenPrice(uint256 _round, uint256 _price) external onlyOwner { tokenPrices[_round] = _price; } // Function to allocate tokens to users based on USDe token payment function allocateTokens(uint256 _amount, uint256 _round) external { require(_amount > 0, "Amount must be greater than 0"); require(_round > 0, "Round must be greater than 0"); uint256 price = tokenPrices[_round]; uint256 tokensToAllocate = _amount * price; require(tokensToAllocate <= tokenAllocations[_round], "Not enough tokens available for allocation"); // Transfer USDe tokens from sender USDeToken.transferFrom(msg.sender, address(this), _amount); // Transfer e2W tokens to sender e2WToken.transfer(msg.sender, tokensToAllocate); // Reduce available token allocation tokenAllocations[_round] -= tokensToAllocate; // Update balances balances[msg.sender] += tokensToAllocate; } // Function to issue reward tokens function issueRewards(uint256 _amount) external onlyOwner { require(_amount <= rewardAllocation, "Not enough reward tokens available"); // Transfer reward tokens to reward address e2WToken.transfer(rewardAddress, _amount); // Reduce available reward allocation rewardAllocation -= _amount; } // Function to distribute dividends (DCPoints) to token holders function distributeDividends(address _dcPointsContract) external onlyOwner { IERC20 dcPoints = IERC20(_dcPointsContract); // Calculate total DCPoints balance in the DCPoints contract uint256 totalDCPoints = dcPoints.balanceOf(address(this)); // Distribute DCPoints to token holders based on their ratio of token holding for (uint256 i = 0; i < totalSupply; i++) { address holder = address(uint160(i)); // Convert uint256 to address uint256 balance = balances[holder]; uint256 dividend = (balance * totalDCPoints) / totalSupply; // Transfer dividend (DCPoints) to holder dcPoints.transfer(holder, dividend); } } // Function to start a voting process for choosing reward address function startRewardAddressVoting(string memory _referenceNumber) external { require(bytes(_referenceNumber).length == 6, "Reference number must be 6 characters long"); require(votings[_referenceNumber].startTime == 0, "Voting process with this reference number already exists"); votings[_referenceNumber].startTime = block.timestamp; votings[_referenceNumber].endTime = block.timestamp + votingDuration; votings[_referenceNumber].initiator = msg.sender; votings[_referenceNumber].referenceNumber = _referenceNumber; } // Function to vote for choosing reward address function voteForRewardAddress(string memory _referenceNumber) external { require(votings[_referenceNumber].startTime != 0, "No voting process found with this reference number"); require(block.timestamp < votings[_referenceNumber].endTime, "Voting process has ended"); votings[_referenceNumber].votes[msg.sender] = true; } // Function to finalize voting for choosing reward address and set the reward address function finalizeRewardAddressVoting(string memory _referenceNumber, address _newRewardAddress) external { require(votings[_referenceNumber].startTime != 0, "No voting process found with this reference number"); require(block.timestamp >= votings[_referenceNumber].endTime, "Voting process not ended yet"); require(msg.sender == votings[_referenceNumber].initiator, "Only the voting initiator can finalize the voting process"); uint256 yesVotes; uint256 totalVotes; // Calculate total votes and yes votes for (uint256 i = 0; i < totalSupply; i++) { address holder = address(uint160(i)); if (votings[_referenceNumber].votes[holder]) { yesVotes++; } totalVotes++; } // Check if 10% of total token holders voted yes require((yesVotes * 100) / totalVotes >= votingThreshold, "10% threshold not met"); // Set the new reward address rewardAddress = _newRewardAddress; } // Additional functions for governance and voting can be added here // Function to update reward allocation function updateRewardAllocation(uint256 _amount) external onlyOwner { rewardAllocation = _amount; } // Function to get the balance of DCPoints held by the contract function getDCPointsBalance(address _dcPointsContract) external view returns (uint256) { IERC20 dcPoints = IERC20(_dcPointsContract); return dcPoints.balanceOf(address(this)); } // Function to allow deposit of tokens function deposit(address _token, uint256 _amount) external { require(allowedTokens[_token], "Token not allowed"); IERC20(_token).transferFrom(msg.sender, address(this), _amount); } // Function to allow withdrawal of tokens by e2W token holders with more than 14% ownership function withdraw(address _token, uint256 _amount) external { require(allowedTokens[_token], "Token not allowed"); require((balances[msg.sender] * 100) / totalSupply > 14, "Ownership percentage below threshold"); IERC20(_token).transfer(msg.sender, _amount); } // Function to set the allowed status of a token function setTokenAllowed(address _token, bool _allowed) external onlyOwner { allowedTokens[_token] = _allowed; } // Function to set the voting duration function setVotingDuration(uint256 _duration) external onlyOwner { votingDuration = _duration; } // Function to set the voting threshold function setVotingThreshold(uint256 _threshold) external onlyOwner { votingThreshold = _threshold; } // Function to get the contract count function getContractCount() external view returns (uint256) { return contracts.length; } }