// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "./USDT.sol"; import "./Valhalla.sol"; struct VillaDetail { uint price; uint id; uint maxLot; uint sold; address fundraiser; } contract BaliVilla is Initializable, ERC1155Upgradeable, OwnableUpgradeable { /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } ERC20 public usdt; Valhalla public valhalla; uint public totalList; mapping(uint => VillaDetail) public villa; mapping(address => uint) public sponsorReward; address[2] public developerAccounts; function initialize( ERC20 _usdt, Valhalla _valhalla, address developer1, address developer2 ) public initializer { __ERC1155_init("https://globalnetwork.finance/api/erc1155/nft-villa/"); __Ownable_init(); usdt = _usdt; valhalla = _valhalla; developerAccounts[0] = developer1; developerAccounts[1] = developer2; } function setURI(string memory newuri) public onlyOwner { _setURI(newuri); } function mint( address account, uint256 id, uint256 amount, bytes memory data ) public onlyOwner { _mint(account, id, amount, data); } function mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public onlyOwner { _mintBatch(to, ids, amounts, data); } function addNewVilla( uint _price, uint _maxLot, address _fundraiser ) public onlyOwner { uint id = totalList; VillaDetail storage _villa = villa[id]; _villa.price = _price; _villa.maxLot = _maxLot; _villa.fundraiser = _fundraiser; _villa.sold = 0; _villa.id = id; totalList++; } function updateVilla(uint _id, uint _price, uint _maxLot) public onlyOwner { VillaDetail storage _villa = villa[_id]; require(_id <= totalList, "wrong method, no villa available"); _villa.price = _price; _villa.maxLot = _maxLot; } function getVilla(uint _id) public view returns (VillaDetail memory) { VillaDetail storage _villa = villa[_id]; return _villa; } function buyVilla(uint _id, uint _amount) public { VillaDetail storage _villa = villa[_id]; require(_villa.price > 0, "wrong villa id, no villa available"); // villa update s _villa.sold += _amount; require( _villa.sold <= _villa.maxLot, "fraction completed, no token available" ); uint totalPrice = _villa.price * _amount; uint developersFee = (totalPrice * 17691) / 100000; // 17,691% uint feePerDev = developersFee / 2; address referall; uint rest; // share reward impl (, , , referall, , , , ) = valhalla.accountMap(msg.sender); for (uint i = 0; i < 4; i++) { if (referall == address(0)) break; // provide 5,3,2 percentage by skip the 4 if (i == 1) continue; uint percentage = 5 - i; // store the value sponsorReward[referall] += (totalPrice * percentage) / 100; rest += (totalPrice * percentage) / 100; // replace referral (, , , referall, , , , ) = valhalla.accountMap(referall); } usdt.transferFrom(msg.sender, developerAccounts[0], feePerDev); usdt.transferFrom(msg.sender, developerAccounts[1], feePerDev); // end share reward impl usdt.transferFrom(msg.sender, address(this), rest); usdt.transferFrom( msg.sender, _villa.fundraiser, totalPrice - rest - developersFee ); _mint(msg.sender, _id, _amount, ""); } function claimSponsorReward() public { uint reward = sponsorReward[msg.sender]; require(reward > 0, "no reward to be claimed"); sponsorReward[msg.sender] = 0; usdt.transfer(msg.sender, reward); } function setDeveloperAccounts(address dev1, address dev2) public onlyOwner { developerAccounts[0] = dev1; developerAccounts[1] = dev2; } function wdUSDT(uint amount) public onlyOwner() { require(amount <= usdt.balanceOf(address(this)), "Insufficient USDT balance"); usdt.transfer(msg.sender, amount); } }