|
|
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "./NFT.sol"; import "./Pool.sol"; import "./PledgeType.sol"; import "./Utils.sol";
contract Pledge is Initializable {
NFT nftContract; Pool poolContract; ProductInfo[] public productInfo; mapping(uint256 => PledgeType) pledges; mapping(address => PledgeType[]) public pledgeRecords; mapping(uint256 => PledgeType) public invitationPledges; mapping(address => RecommendObjType) public recommendObj; mapping(address => uint256[]) public invitationTokens; mapping(address => address[]) public invitationAddress; mapping(address => PledgeWithdrawRecordType[]) public pledgeWithdrawRecord; mapping(address => InvitationWithdrawRecordType[]) public invitationWithdrawRecord; address[] public blackList; address[] public whiteList; mapping(address => PledgeType[]) public pledgeDestoryRecords; uint256 public invitationRate; uint256 public nextTokenId; bool public pledgeStatus; uint256 public dayTime;
function initialize(address nftAddress, address poolAddress) public initializer { nftContract = NFT(nftAddress); poolContract = Pool(poolAddress); nextTokenId = 1; invitationRate = 1; pledgeStatus = false; dayTime = 1 days; productInfo.push(ProductInfo(180, 14)); productInfo.push(ProductInfo(270, 15)); productInfo.push(ProductInfo(360, 16)); }
modifier onlyAdmin (){ address[] memory _admins = nftContract.getAdmin(); bool _isAdmin = Utils.isAdmin(_admins, msg.sender); require(_isAdmin == true,"For administrators only"); _; }
modifier onlyBlacks (){ bool _isBlack = Utils.isAdmin(blackList, msg.sender); require(_isBlack == false,"You've been blacklisted."); _; }
function getPledgeRecords(address _owner) public view returns(PledgeType[] memory){ return pledgeRecords[_owner]; }
function getPledgeWithdrawRecord(address _owner) public view returns(PledgeWithdrawRecordType[] memory){ return pledgeWithdrawRecord[_owner]; }
function getInvitationWithdrawRecord(address _owner) public view returns(InvitationWithdrawRecordType[] memory){ return invitationWithdrawRecord[_owner]; }
function getPledgeDestoryRecords(address _owner) public view returns(PledgeType[] memory){ return pledgeDestoryRecords[_owner]; }
function getProductInfo() public view returns (ProductInfo[] memory) { return productInfo; }
function getOwnerAllPledgeInfo( address _ownerAddress ) public view returns (PledgeType[] memory result) { uint256[] memory tokens = getOwnerAllTokens(_ownerAddress); result = new PledgeType[](tokens.length); for (uint256 i = 0; i < tokens.length; i++) { result[i] = pledges[tokens[i]]; } return result; }
function bindRecommend(address _referrer) internal { require(recommendObj[msg.sender].key == address(0),"Already have recommenders"); require(msg.sender != _referrer ,"You can't recommend yourself."); require(recommendObj[_referrer].referrer != msg.sender,"Can't recommend each other"); recommendObj[msg.sender] = RecommendObjType( msg.sender, _referrer, block.timestamp, 0 ); invitationAddress[_referrer].push(msg.sender); } function setInvitationIncomes(PledgeType memory _pledge) internal { address recommendAddr = recommendObj[msg.sender].referrer; PledgeType memory _invitationPledge = _pledge; _invitationPledge.rate = invitationRate; uint256 amount = _invitationPledge.pledgeAmount; uint256 rate = _invitationPledge.rate; uint256 day = _invitationPledge.pledgeDay; uint256 tokenId = _invitationPledge.tokenId; uint256 contribute = (((amount * rate) / 365) * day) / 100; recommendObj[msg.sender].contribute += contribute; if (invitationTokens[recommendAddr].length == 0) { invitationTokens[recommendAddr] = new uint256[](0); } if (invitationAddress[recommendAddr].length == 0) { invitationAddress[recommendAddr] = new address[](0); } invitationTokens[recommendAddr].push(tokenId); invitationPledges[tokenId] = _invitationPledge; }
function pledge(uint256 amount, uint256 index, address _referrer) external onlyBlacks { bool _isWhite = Utils.isAdmin(whiteList, msg.sender); if(!_isWhite){ require(pledgeStatus == false,"The pledge is closed."); } require(amount >= 1, "Minimum pledge 1FIL"); require(index < productInfo.length, "Product does not exist"); poolContract.deposit(msg.sender, amount); uint256 tokenId = nextTokenId++; if (_referrer != address(0)) { bindRecommend(_referrer); }
ProductInfo memory item = productInfo[index]; uint256 startTime = block.timestamp; uint256 endTime = block.timestamp + (item.day * dayTime); nftContract.mint(msg.sender, tokenId); PledgeType memory _pledge = PledgeType(tokenId,startTime,endTime,startTime,amount,item.rate,item.day,msg.sender,false); pledges[tokenId] = _pledge; pledgeRecords[msg.sender].push(_pledge); if (recommendObj[msg.sender].key != address(0)) { setInvitationIncomes(_pledge); } }
function getOwnerAllTokens( address _ownerAddress ) public view returns (uint256[] memory) { uint256 nftAmount = nftContract.balanceOf(_ownerAddress); uint256[] memory tokens = new uint256[](nftAmount); for (uint256 i = 0; i < nftAmount; i++) { tokens[i] = nftContract.tokenOfOwnerByIndex(_ownerAddress, i); } return tokens; }
function calculateInterest( PledgeType memory _pledge ) public view returns (uint256) { uint256 total_amount = _pledge.pledgeAmount; uint256 currentTime = block.timestamp; uint256 withdrawTime = _pledge.withdrawTime; uint256 rate = _pledge.rate; if(_pledge.endTime < currentTime){ currentTime = _pledge.endTime; } uint256 daysPassed = (currentTime - withdrawTime) / dayTime; uint256 dailyShare = (((total_amount * rate) / 365) * daysPassed) / 100; return dailyShare; }
function getWithdrawbleAmount( address _owner ) public view returns (uint256) { uint256[] memory tokens = getOwnerAllTokens(_owner); if (tokens.length <= 0) return 0; uint256 _total_interest = 0; for (uint256 i = 0; i < tokens.length; i++) { uint256 _tokenId = tokens[i]; PledgeType memory _item = pledges[_tokenId]; _total_interest += calculateInterest(_item); } return _total_interest; }
function withdraAllInterest() external onlyBlacks { uint256 _total_interest = getWithdrawbleAmount(msg.sender); require(_total_interest > 0, "Withdrawal amount must be greater than 0"); uint256[] memory tokens = getOwnerAllTokens(msg.sender); for(uint256 i=0;i<tokens.length;i++){ uint256 _withdrawTime = block.timestamp; uint256 _tokenId = tokens[i]; require(!pledges[_tokenId].isBlack,"Unable to withdraw, the NFT Tokend is blacklisted."); if(pledges[_tokenId].endTime < _withdrawTime){ _withdrawTime = pledges[_tokenId].endTime; } pledges[_tokenId].withdrawTime = _withdrawTime; } poolContract.withdraw(msg.sender, _total_interest); pledgeWithdrawRecord[msg.sender].push(PledgeWithdrawRecordType(_total_interest,block.timestamp,0,0,2)); }
function withdrawInterest(uint256 tokenId) external onlyBlacks { address _owner = nftContract.ownerOf(tokenId); require(_owner == msg.sender,"It's not a contract."); PledgeType memory data = pledges[tokenId]; require(!data.isBlack,"Unable to withdraw,the NFT Tokend is blacklisted."); uint256 _interest = calculateInterest(data); require(_interest > 0, "Withdrawal amount must be greater than 0"); uint256 _withdrawTime = block.timestamp; if(data.endTime < _withdrawTime){ _withdrawTime = data.endTime; } poolContract.withdraw(msg.sender, _interest); pledges[tokenId].withdrawTime = _withdrawTime; pledgeWithdrawRecord[msg.sender].push(PledgeWithdrawRecordType(_interest,block.timestamp,data.tokenId,data.pledgeDay,1));
}
function getOwnerInvitationPledges( address addr ) public view returns (PledgeType[] memory result) { uint256[] memory _tokens = invitationTokens[addr]; result = new PledgeType[](_tokens.length); for (uint256 i = 0; i < _tokens.length; i++) { uint256 _tokenId = _tokens[i]; result[i] = invitationPledges[_tokenId]; } return result; }
function getOwnerAllInvitationWithdrawAmout(address owner) public view returns(uint256){ uint256 _income = 0; PledgeType[] memory _pledges = getOwnerInvitationPledges(owner); for(uint256 i=0;i<_pledges.length;i++){ PledgeType memory data = _pledges[i]; _income += calculateInterest(data); } return _income; }
function withdraInvitationAllInterest() external onlyBlacks { uint256 _total_interest = getOwnerAllInvitationWithdrawAmout(msg.sender); require(_total_interest > 0, "Withdrawal amount must be greater than 0"); uint256[] memory tokens = invitationTokens[msg.sender]; for(uint256 i=0;i<tokens.length;i++){ uint256 _withdrawTime = block.timestamp; uint256 _tokenId = tokens[i]; if(invitationPledges[_tokenId].endTime < _withdrawTime){ _withdrawTime = invitationPledges[_tokenId].endTime; } invitationPledges[_tokenId].withdrawTime = _withdrawTime; } uint256 currentTime = block.timestamp; poolContract.withdraw(msg.sender, _total_interest); invitationWithdrawRecord[msg.sender].push(InvitationWithdrawRecordType(_total_interest,currentTime)); }
function withdrawInvitationInterest(uint256 tokenId) external onlyBlacks { uint256[] memory _tokens = invitationTokens[msg.sender]; bool _owner = false; for(uint256 i=0;i<_tokens.length;i++){ uint256 _tokenId = _tokens[i]; if(_tokenId == tokenId){ _owner = true; break; } } require(_owner == true,"It's not a contract."); PledgeType memory data = invitationPledges[tokenId]; uint256 _interest = calculateInterest(data); require(_interest > 0, "Withdrawal amount must be greater than 0"); uint256 _withdrawTime = block.timestamp; if(data.endTime < _withdrawTime){ _withdrawTime = data.endTime; } poolContract.withdraw(msg.sender, _interest); uint256 currentTime = block.timestamp; invitationPledges[tokenId].withdrawTime = _withdrawTime; invitationWithdrawRecord[msg.sender].push(InvitationWithdrawRecordType(_interest,currentTime)); }
function getAllInvitationMember( address addr ) public view returns (RecommendObjType[] memory result) { address[] memory _addresss = invitationAddress[addr]; result = new RecommendObjType[](_addresss.length); for (uint256 i = 0; i < _addresss.length; i++) { result[i] = recommendObj[_addresss[i]]; } return result; }
function getCurrentTime() public view returns (uint256){ uint256 currentTime = block.timestamp; return currentTime; }
function destroyPledge(uint256 tokenId) external onlyBlacks{ address _owner = nftContract.ownerOf(tokenId); require(_owner == msg.sender,"You're not a contract owner."); uint256 currentTime = block.timestamp; PledgeType memory data = pledges[tokenId]; require(data.endTime < currentTime,"Unexpired Pledge Agreement"); nftContract.transferFrom(msg.sender,address(this), tokenId); poolContract.withdraw(msg.sender, data.pledgeAmount); data.withdrawTime = currentTime; pledgeDestoryRecords[msg.sender].push(data); }
function setInvitationRate(uint256 _rate) external onlyAdmin{ invitationRate = _rate; }
function setPledgeStatus(bool _status) external onlyAdmin { pledgeStatus = _status; }
function addBlackOrWhiteList(address[] memory _blacks,uint256 _type) external onlyAdmin { require(_blacks.length>0,"Enter at least one address"); if(_type == 1){ address[] memory blacks = Utils.addAdmin(blackList, _blacks); blackList = blacks; } if(_type == 2){ address[] memory whites = Utils.addAdmin(whiteList, _blacks); whiteList = whites; } }
function delBlackOrWhiteList(address[] memory _blacks,uint256 _type) external onlyAdmin{ require(_blacks.length>0,"Enter at least one address"); if(_type == 1){ address[] memory blacks = Utils.deleteAdmin(blackList, _blacks); blackList = blacks; } if(_type == 2){ address[] memory whites = Utils.deleteAdmin(whiteList, _blacks); whiteList = whites; } }
function getBlackOrWhiteList(uint256 _type) public view returns (address[] memory) { return _type == 1 ? blackList : whiteList; }
function setProductInfo(uint256[] memory _days,uint256[] memory _rates) external onlyAdmin { delete productInfo; for(uint256 i=0;i<3;i++){ productInfo.push(ProductInfo(_days[i],_rates[i])); } }
function getDetails(uint256 tokenId,uint256 _type) public view returns(PledgeType memory){ if(_type == 1){ return pledges[tokenId]; } return invitationPledges[tokenId]; }
function addNftBalcks(uint256[] memory _tokenIds) external onlyAdmin { require(_tokenIds.length > 0,"Parameter is empty"); nftContract.addBlacks(_tokenIds); for(uint256 i=0;i<_tokenIds.length;i++){ uint256 _id = _tokenIds[i]; require(pledges[_id].sender != address(0), "NFT ID does not exist"); require(!pledges[_id].isBlack,"NFT ID already exists"); pledges[_id].isBlack = true; } }
function deleteNftBlacks(uint256[] memory _ids) external onlyAdmin { require(_ids.length > 0,"Parameter is empty"); nftContract.delBlacks(_ids); for(uint256 i=0;i<_ids.length;i++){ uint256 _id = _ids[i]; require(pledges[_id].sender != address(0), "NFT ID does not exist"); pledges[_id].isBlack = false; } }
}
|