// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "/e2XUsers1.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract TCPointContract is Ownable { e2XUsernames public userDataContract; IERC20 public e2xToken; uint256 public pointsPerToken; address public tcPointBurntAccount; struct TCPointBalance { uint128 balance; // Represents TCPoints balance in multiples of 100 } // Decimal scaling factor uint8 private constant DECIMALS = 18; modifier onlyAdminOrAuthorizedContract() { require(tcPointsAdmins[msg.sender] || authorizedContracts[msg.sender] || msg.sender == owner(), "Not authorized"); _; } modifier deductTCPCharges(address _fromUser) { // Deduct 1 TCPoint from sender and send it to admin tcBalance[_fromUser].balance -= 1; tcBalance[owner()].balance += 1; emit TCPointDeducted(_fromUser, owner(), 1); _; // Continue with the actual function execution } mapping(address => TCPointBalance) public tcBalance; mapping(address => uint256) public totalTCBalance; mapping(address => bool) public tcPointsAdmins; mapping(address => bool) public authorizedContracts; event PointsRatioUpdated(uint256 newPointsPerToken); event TCPUpdated(address user, uint256 amount, bool added); event AdminAdded(address indexed admin); event AdminRemoved(address indexed admin); event ContractAuthorized(address indexed contractAddress); event ContractUnauthorized(address indexed contractAddress); event TCPointDeducted(address indexed from, address indexed to, uint256 amount); constructor(address _userDataContract, address _e2xToken) { userDataContract = e2XUsernames(_userDataContract); e2xToken = IERC20(_e2xToken); pointsPerToken = 100; // 100 TCP per E2X token initially tcPointsAdmins[msg.sender] = true; // Set contract deployer as admin by default } function setPointsPerToken(uint256 _newPointsPerToken) external onlyOwner { pointsPerToken = _newPointsPerToken; emit PointsRatioUpdated(_newPointsPerToken); } function addAdmin(address _admin) external onlyOwner { require(_admin != address(0), "Invalid admin address"); tcPointsAdmins[_admin] = true; emit AdminAdded(_admin); } function removeAdmin(address _admin) external onlyOwner { require(tcPointsAdmins[_admin], "Address is not an admin"); tcPointsAdmins[_admin] = false; emit AdminRemoved(_admin); } function authorizeContract(address _contractAddress) external onlyOwner { require(_contractAddress != address(0), "Invalid contract address"); authorizedContracts[_contractAddress] = true; emit ContractAuthorized(_contractAddress); } function unauthorizeContract(address _contractAddress) external onlyOwner { require(authorizedContracts[_contractAddress], "Contract is not authorized"); authorizedContracts[_contractAddress] = false; emit ContractUnauthorized(_contractAddress); } function transferE2XToken(uint256 _amount) external { require(_amount > 0, "Amount must be greater than 0"); require(e2xToken.transferFrom(msg.sender, address(this), _amount), "E2X token transfer failed"); address userAddress = msg.sender; // Calculate the number of TCPoints to mint based on the transferred E2X tokens uint256 tcPointsToMint = fraction(_amount, 1 ether); // 1 ether represents 1 E2X token // Mint TCPoints to the user tcBalance[userAddress].balance += uint128(tcPointsToMint); totalTCBalance[userAddress] += tcPointsToMint; emit TCPUpdated(userAddress, tcPointsToMint, true); } function transferTCP(address _toUser, uint256 _amount) external deductTCPCharges(msg.sender) { address senderAddress = msg.sender; uint128 senderBalance = tcBalance[senderAddress].balance; uint128 amount = uint128(_amount); // Convert balances and amount to decimal system uint256 senderBalanceDecimal = uint256(senderBalance) * (10**DECIMALS); uint256 amountDecimal = uint256(amount) * (10**DECIMALS); require(senderBalanceDecimal >= amountDecimal, "Insufficient TCP balance"); // Perform the transfer in decimal system uint256 newSenderBalanceDecimal = senderBalanceDecimal - amountDecimal; uint256 newRecipientBalanceDecimal = uint256(tcBalance[_toUser].balance) * (10**DECIMALS) + amountDecimal; // Update balances in fixed-point arithmetic tcBalance[senderAddress].balance = uint128(newSenderBalanceDecimal / (10**DECIMALS)); tcBalance[_toUser].balance = uint128(newRecipientBalanceDecimal / (10**DECIMALS)); emit TCPointDeducted(senderAddress, _toUser, _amount); } function transferTCPBetweenMembers(string calldata _fromUser, string calldata _toUser, uint256 _amount) external deductTCPCharges(msg.sender) { // Get the sender's address address senderAddress = msg.sender; // Get the addresses associated with the provided e2xdata usernames address fromUserAddress = userDataContract.getAddressByUser(_fromUser); address toUserAddress = userDataContract.getAddressByUser(_toUser); // Ensure that the sender is the owner of the e2xdata address (_fromUser) require(fromUserAddress == senderAddress, "Sender is not the owner of the e2xdata address"); // Check if the e2xdata addresses exist require(fromUserAddress != address(0) && toUserAddress != address(0), "Invalid e2xdata addresses"); uint128 fromUserBalance = tcBalance[fromUserAddress].balance; uint128 amount = uint128(_amount); // Convert balances and amount to decimal system uint256 fromUserBalanceDecimal = uint256(fromUserBalance) * (10**DECIMALS); uint256 amountDecimal = uint256(amount) * (10**DECIMALS); require(fromUserBalanceDecimal >= amountDecimal, "Insufficient TCP balance"); // Deduct 1 TCPoint from the sender and transfer it to the admin uint256 newSenderBalanceDecimal = fromUserBalanceDecimal - amountDecimal; uint256 newRecipientBalanceDecimal = uint256(tcBalance[toUserAddress].balance) * (10**DECIMALS) + amountDecimal; // Update balances in fixed-point arithmetic tcBalance[fromUserAddress].balance = uint128(newSenderBalanceDecimal / (10**DECIMALS)); tcBalance[toUserAddress].balance = uint128(newRecipientBalanceDecimal / (10**DECIMALS)); // Emit an event to log the TCP transfer emit TCPointDeducted(fromUserAddress, toUserAddress, _amount); } // Rest of the contract functions... function fraction(uint256 numerator, uint256 denominator) internal pure returns (uint256) { require(denominator > 0, 'TCPointContract::fraction: division by zero'); if (numerator == 0) return 0; uint256 result = (numerator * (1 ether)) / denominator; require(result <= type(uint224).max, 'TCPointContract::fraction: overflow'); return result; } }