编译器
0.8.22+commit.4fc1097e
文件 1 的 14:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 14:ContractMetadata.sol
pragma solidity ^0.8.0;
import "./interface/IContractMetadata.sol";
abstract contract ContractMetadata is IContractMetadata {
error ContractMetadataUnauthorized();
string public override contractURI;
function setContractURI(string memory _uri) external override {
if (!_canSetContractURI()) {
revert ContractMetadataUnauthorized();
}
_setupContractURI(_uri);
}
function _setupContractURI(string memory _uri) internal {
string memory prevURI = contractURI;
contractURI = _uri;
emit ContractURIUpdated(prevURI, _uri);
}
function _canSetContractURI() internal view virtual returns (bool);
}
文件 3 的 14:IContractMetadata.sol
pragma solidity ^0.8.0;
interface IContractMetadata {
function contractURI() external view returns (string memory);
function setContractURI(string calldata _uri) external;
event ContractURIUpdated(string prevURI, string newURI);
}
文件 4 的 14:IERC20.sol
pragma solidity ^0.8.20;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
文件 5 的 14:IMulticall.sol
pragma solidity ^0.8.0;
interface IMulticall {
function multicall(bytes[] calldata data) external returns (bytes[] memory results);
}
文件 6 的 14:IPermissions.sol
pragma solidity ^0.8.0;
interface IPermissions {
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
文件 7 的 14:IPermissionsEnumerable.sol
pragma solidity ^0.8.0;
import "./IPermissions.sol";
interface IPermissionsEnumerable is IPermissions {
function getRoleMember(bytes32 role, uint256 index) external view returns (address);
function getRoleMemberCount(bytes32 role) external view returns (uint256);
}
文件 8 的 14:Miracle-Asset-Master.sol
pragma solidity ^0.8.0;
contract AssetMaster {
address public owner;
address[] public erc20Whitelist;
address[] public erc721Whitelist;
address[] public erc1155Whitelist;
mapping(address => bool) private erc20Listed;
mapping(address => bool) private erc721Listed;
mapping(address => bool) private erc1155Listed;
address public feeToken;
uint256 public tournamentCreationFee;
uint256 public tournamentParticipationFee;
address public feeRecipient;
constructor() {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner, "Not the owner");
_;
}
function addToERC20Whitelist(address _token) public onlyOwner {
require(!erc20Listed[_token], "Token already whitelisted");
erc20Whitelist.push(_token);
erc20Listed[_token] = true;
}
function removeFromERC20Whitelist(address _token) public onlyOwner {
require(erc20Listed[_token], "Token not in whitelist");
remove(erc20Whitelist, _token);
erc20Listed[_token] = false;
}
function addToERC721Whitelist(address _token) public onlyOwner {
require(!erc721Listed[_token], "Token already whitelisted");
erc721Whitelist.push(_token);
erc721Listed[_token] = true;
}
function removeFromERC721Whitelist(address _token) public onlyOwner {
require(erc721Listed[_token], "Token not in whitelist");
remove(erc721Whitelist, _token);
erc721Listed[_token] = false;
}
function addToERC1155Whitelist(address _token) public onlyOwner {
require(!erc1155Listed[_token], "Token already whitelisted");
erc1155Whitelist.push(_token);
erc1155Listed[_token] = true;
}
function removeFromERC1155Whitelist(address _token) public onlyOwner {
require(erc1155Listed[_token], "Token not in whitelist");
remove(erc1155Whitelist, _token);
erc1155Listed[_token] = false;
}
function remove(address[] storage array, address _token) internal {
uint length = array.length;
for (uint i = 0; i < length; i++) {
if (array[i] == _token) {
array[i] = array[length - 1];
array.pop();
break;
}
}
}
function setTournamentFeeToken(address _token) public onlyOwner {
feeToken = _token;
}
function setTournamentCreationFee(uint256 _fee) public onlyOwner {
tournamentCreationFee = _fee;
}
function setTournamentParticipationFee(uint256 _fee) public onlyOwner {
tournamentParticipationFee = _fee;
}
function setFeeRecipient(address _address) public onlyOwner {
feeRecipient = _address;
}
}
文件 9 的 14:Miracle-Fundable-Escrow.sol
pragma solidity ^0.8.22;
import "./Miracle-Asset-Master.sol";
import "./Miracle-Fundable-Tournament.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@thirdweb-dev/contracts/extension/PermissionsEnumerable.sol";
import "@thirdweb-dev/contracts/extension/Multicall.sol";
import "@thirdweb-dev/contracts/extension/ContractMetadata.sol";
interface IMintableERC20 is IERC20 {
function mintTo(address to, uint256 amount) external;
}
interface IStakingContract {
function stakings(address user) external view returns (uint256, uint256, uint256);
}
interface iMiraclePass {
function hasValidPremiumPass(address user) external view returns (bool);
function hasValidPlatinumPass(address user) external view returns (bool);
}
contract FundableTournamentEscrow is PermissionsEnumerable, Multicall, ContractMetadata {
address public deployer;
address public admin;
uint public RoyaltyPrizeDev;
uint public RoyaltyRegfeeDev;
uint public RoyaltyPrizeFlp;
uint public RoyaltyRegfeeFlp;
uint public RoyaltyPrizeReferee;
uint public RoyaltyRegfeeReferee;
address public royaltyAddrDev;
address public royaltyAddrFlp;
uint public minFundingRate;
uint public baseLimit;
AssetMaster public assetMasterAddr;
IStakingContract[] public stakingContracts;
iMiraclePass public miraclePass;
bytes32 public constant TOURNAMENT_ROLE = keccak256("TOURNAMENT_ROLE");
bytes32 public constant FACTORY_ROLE = keccak256("FACTORY_ROLE");
FundableTournament public miracletournament;
struct Tournament {
address organizer;
bool isFunding;
bool isSponsored;
uint tier;
IERC20 prizeToken;
IERC20 feeToken;
uint prizeAmount;
uint joinFee;
uint feeBalance;
uint256[] prizeAmountArray;
bool tournamentCreated;
bool tournamentEnded;
bool tournamentCanceled;
string tournamentURI;
address[] referees;
uint PlayersLimit;
}
mapping(uint => Tournament) public tournamentMapping;
struct Funding {
uint256 startTime;
uint256 endTime;
IERC20 fundingToken;
uint256 totalFunded;
uint256 fundingGoal;
bool fundingActive;
bool fundingEnded;
bool fundingCanceled;
mapping(address => uint256) contributions;
address[] contributors;
}
mapping(uint => Funding) public fundingMapping;
event UnlockPrize(uint tournamentId, uint amount);
event UnlockFee(uint tournamentId, uint amount);
constructor(address _royaltyAddrDev, address _royaltyAddrFlp, address[] memory _stakingContractAddresses, address _assetMasterAddr, address _miracletournament, address _miraclePass, string memory _contractURI) {
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
royaltyAddrDev = _royaltyAddrDev;
royaltyAddrFlp = _royaltyAddrFlp;
for (uint i = 0; i < _stakingContractAddresses.length; i++) {
stakingContracts.push(IStakingContract(_stakingContractAddresses[i]));
}
RoyaltyPrizeDev = 5;
RoyaltyRegfeeDev = 5;
RoyaltyPrizeFlp = 5;
RoyaltyRegfeeFlp = 5;
RoyaltyPrizeReferee = 5;
RoyaltyRegfeeReferee = 0;
minFundingRate = 100;
baseLimit = 200e6;
deployer = msg.sender;
assetMasterAddr = AssetMaster(_assetMasterAddr);
_setupRole(TOURNAMENT_ROLE, _miracletournament);
miracletournament = FundableTournament(_miracletournament);
miraclePass = iMiraclePass(_miraclePass);
_setupContractURI(_contractURI);
_setupRole(FACTORY_ROLE, msg.sender);
}
event EscrowCreated(uint tournamentId, address organizer);
event Registration(uint tournamentId, address user);
event KickPlayer(uint tournamentId, address user);
event Fund(uint tournamentId, address fundingUser, uint256 fundingAmount);
event FundEnded(uint tournamentId);
event FundCanceled(uint tournamentId);
event TournamentEnded(uint tournamentId);
event TournamentCanceled(uint tournamentId);
function _canSetContractURI() internal view virtual override returns (bool){
return msg.sender == deployer;
}
modifier onlyOrganizer(uint _tournamentId){
Tournament storage _tournament = tournamentMapping[_tournamentId];
require(msg.sender == _tournament.organizer, "Only organizer can call this function");
_;
}
function connectEditionStakings(address[] memory _stakingContractAddresses) external onlyRole(DEFAULT_ADMIN_ROLE){
delete stakingContracts;
for (uint i = 0; i < _stakingContractAddresses.length; i++) {
stakingContracts.push(IStakingContract(_stakingContractAddresses[i]));
}
}
function connectTournament(address _miracletournament) external onlyRole(DEFAULT_ADMIN_ROLE){
_setupRole(TOURNAMENT_ROLE, _miracletournament);
miracletournament = FundableTournament(_miracletournament);
}
function connectAssestMaster(address _assetMasterAddr) external onlyRole(DEFAULT_ADMIN_ROLE){
assetMasterAddr = AssetMaster(_assetMasterAddr);
}
function connectMiraclePass(address _miraclePassAddr) external onlyRole(DEFAULT_ADMIN_ROLE){
miraclePass = iMiraclePass(_miraclePassAddr);
}
function createTournamentEscrow(uint256[] memory _tournamentInfo, bool _isFunding, address[] memory _prizeFeeToken, uint256[] memory _prizeFeeAmount, uint256[] memory _regStartEndTime, uint256[] memory _FundStartEndTime, uint256[] memory _prizeAmountArray, string memory _tournamentURI, uint _playerLimit, address[] memory _referees) external {
require(_FundStartEndTime[0] < _FundStartEndTime[1], "Invalid funding time range");
require(_regStartEndTime[0] < _regStartEndTime[1], "Invalid join tournament time range");
uint256 totalWithdrawAmount;
for (uint256 i = 0; i < _prizeAmountArray.length; i++) {
totalWithdrawAmount += _prizeAmountArray[i];
}
require(totalWithdrawAmount == _prizeFeeAmount[0], "Total prize amount must equal prize amount.");
Tournament storage newTournament = tournamentMapping[_tournamentInfo[0]];
require(newTournament.tournamentCreated == false, "Tournament already created.");
bool _isSponsor = isSponsor(msg.sender);
if(!_isSponsor){
if(_isFunding){
revert("Funding tournaments can only be created by sponsors.");
}
}
newTournament.organizer = msg.sender;
newTournament.isFunding = _isFunding;
newTournament.isSponsored = _isSponsor;
newTournament.tier = _tournamentInfo[1];
newTournament.prizeToken = IERC20(_prizeFeeToken[0]);
newTournament.feeToken = IERC20(_prizeFeeToken[1]);
newTournament.joinFee = _prizeFeeAmount[1];
newTournament.feeBalance = 0;
newTournament.prizeAmount = _prizeFeeAmount[0];
newTournament.prizeAmountArray = _prizeAmountArray;
newTournament.tournamentCreated = true;
newTournament.tournamentEnded = false;
newTournament.tournamentCanceled = false;
newTournament.tournamentURI = _tournamentURI;
newTournament.referees = _referees;
newTournament.PlayersLimit = _playerLimit;
miracletournament.createTournament(_tournamentInfo[0], _isFunding, _isSponsor, msg.sender, _regStartEndTime[0], _regStartEndTime[1], _prizeAmountArray.length, _playerLimit);
_payFeeCreate();
if (_isFunding){
createFunding(_tournamentInfo[0], _FundStartEndTime[0], _FundStartEndTime[1], _prizeFeeToken[0], _prizeFeeAmount[0]);
} else {
require(IERC20(_prizeFeeToken[0]).transferFrom(msg.sender, address(this), _prizeFeeAmount[0]), "Transfer failed.");
}
emit EscrowCreated(_tournamentInfo[0], msg.sender);
}
function createFunding(uint _tournamentId, uint _fundStartTime, uint _fundEndTime, address _fundingToken, uint _fundingGoal) internal {
Funding storage funding = fundingMapping[_tournamentId];
require(_fundStartTime < _fundEndTime, "Invalid time range");
require(_fundingToken != address(0), "Invalid token address");
funding.startTime = _fundStartTime;
funding.endTime = _fundEndTime;
funding.fundingToken = IERC20(_fundingToken);
funding.fundingGoal = _fundingGoal;
funding.fundingActive = true;
}
function endedTournament(uint _tournamentId, address[] memory _withdrawAddresses) external onlyRole(TOURNAMENT_ROLE) {
_EndedUnlockFee(_tournamentId);
_EndedUnlockPrize(_tournamentId, _withdrawAddresses);
emit TournamentEnded(_tournamentId);
}
function canceledTournament(uint _tournamentId, address[] memory _entryPlayers) external onlyRole(TOURNAMENT_ROLE) {
_CanceledUnlockTransfer(_tournamentId, _entryPlayers);
emit TournamentCanceled(_tournamentId);
}
function register(uint _tournamentId) external {
Tournament storage _tournament = tournamentMapping[_tournamentId];
require(_tournament.feeToken.allowance(msg.sender, address(this)) >= _tournament.joinFee, "Allowance is not sufficient.");
require(_tournament.joinFee <= _tournament.feeToken.balanceOf(msg.sender), "Insufficient balance.");
require(_tournament.organizer != msg.sender, "Organizers cannot register.");
require(tierValify(_tournament.tier, msg.sender), "There are no required passes for the tournament.");
if (_tournament.isFunding){
Funding storage funding = fundingMapping[_tournamentId];
require(funding.fundingEnded, "Funding is not ended.");
}
_payFeeRegister();
if(_tournament.joinFee > 0){
require(_tournament.feeToken.transferFrom(msg.sender, address(this), _tournament.joinFee), "Transfer failed.");
_tournament.feeBalance = _tournament.feeBalance + _tournament.joinFee;
}
miracletournament.register(_tournamentId, msg.sender);
emit Registration(_tournamentId, msg.sender);
}
function kickPlayer(uint _tournamentId, address _player) external onlyRole(TOURNAMENT_ROLE) {
Tournament storage _tournament = tournamentMapping[_tournamentId];
if(_tournament.joinFee > 0){
require(_tournament.feeToken.transferFrom(address(this), _player, _tournament.joinFee), "Transfer failed.");
_tournament.feeBalance = _tournament.feeBalance - _tournament.joinFee;
}
emit KickPlayer(_tournamentId, msg.sender);
}
function fundTournament(uint _tournamentId, uint256 _amount) external {
Funding storage funding = fundingMapping[_tournamentId];
require(block.timestamp >= funding.startTime && block.timestamp <= funding.endTime, "Funding not active");
require(funding.fundingActive, "Funding not active");
require(funding.totalFunded + _amount <= funding.fundingGoal, "Funding amount exceeds goal");
require(IERC20(funding.fundingToken).allowance(msg.sender, address(this)) >= _amount, "Allowance is not sufficient.");
require(funding.fundingToken.transferFrom(msg.sender, address(this), _amount), "Transfer failed");
require(_amount >= baseLimit, "Amount is less than the minimum required");
require(_amount % baseLimit == 0, "Amount must be in multiples of 200");
uint256 stakedNFTs = getTotalUserStakedAmount(msg.sender);
uint256 maxFundingLimit = calculateMaxFundingLimit(stakedNFTs);
uint256 newTotalContribution = funding.contributions[msg.sender] + _amount;
require(newTotalContribution <= maxFundingLimit, "Total contribution exceeds maximum funding limit");
if (funding.contributions[msg.sender] == 0) {
funding.contributors.push(msg.sender);
}
funding.contributions[msg.sender] = newTotalContribution;
funding.totalFunded += _amount;
emit Fund(_tournamentId, msg.sender, _amount);
}
function endFunding(uint _tournamentId) external onlyRole(TOURNAMENT_ROLE) {
Funding storage funding = fundingMapping[_tournamentId];
require(funding.fundingActive, "Funding not active");
require(funding.totalFunded >= funding.fundingGoal * minFundingRate / 100, "Funding did not reach the minimum rate");
funding.fundingActive = false;
funding.fundingEnded = true;
tournamentMapping[_tournamentId].prizeAmount = funding.totalFunded;
emit FundEnded(_tournamentId);
}
function cancelFunding(uint _tournamentId) external onlyRole(TOURNAMENT_ROLE) {
Funding storage funding = fundingMapping[_tournamentId];
require(funding.fundingActive, "Funding not active");
funding.fundingActive = false;
funding.fundingCanceled = true;
for (uint i = 0; i < funding.contributors.length; i++) {
address contributor = funding.contributors[i];
uint256 amount = funding.contributions[contributor];
funding.fundingToken.transfer(contributor, amount);
}
emit FundCanceled(_tournamentId);
}
function tierValify(uint _gameTier, address user) public view returns (bool) {
if(_gameTier == 1){
return miraclePass.hasValidPremiumPass(user);
}else if(_gameTier == 2){
return miraclePass.hasValidPlatinumPass(user);
}else{
return true;
}
}
function _payFeeCreate() internal {
address feeWallet = assetMasterAddr.feeRecipient();
address feeToken = assetMasterAddr.feeToken();
uint256 amount = assetMasterAddr.tournamentCreationFee();
if(amount > 0){
require(IERC20(feeToken).transferFrom(msg.sender, feeWallet, amount), "Asset master token fee transfer failed.");
}
}
function _payFeeRegister() internal {
address feeWallet = assetMasterAddr.feeRecipient();
address feeToken = assetMasterAddr.feeToken();
uint256 amount = assetMasterAddr.tournamentParticipationFee();
if(amount > 0){
require(IERC20(feeToken).transferFrom(msg.sender, feeWallet, amount), "Asset master token fee transfer failed.");
}
}
function _EndedUnlockFee(uint _tournamentId) internal {
Tournament storage _tournament = tournamentMapping[_tournamentId];
uint256 _feeAmount = _tournament.feeBalance;
uint256 _feeDev = (_feeAmount * RoyaltyRegfeeDev) / 100;
uint256 _feeFlp = (_feeAmount * RoyaltyRegfeeFlp) / 100;
if(_tournament.isFunding){
uint256 _feeForInvestors = _feeAmount - (_feeDev + _feeFlp);
_transferToken(_tournament.feeToken, royaltyAddrDev, _feeDev);
_transferToken(_tournament.feeToken, royaltyAddrFlp, _feeFlp);
Funding storage funding = fundingMapping[_tournamentId];
uint256 totalInvested = funding.totalFunded;
for (uint i = 0; i < funding.contributors.length; i++) {
address investor = funding.contributors[i];
uint256 investedAmount = funding.contributions[investor];
uint256 investorShare = (_feeForInvestors * investedAmount) / totalInvested;
_transferToken(_tournament.feeToken, investor, investorShare);
}
} else {
uint256 _feeOrg = _feeAmount - (_feeDev + _feeFlp);
_transferToken(_tournament.feeToken, royaltyAddrDev, _feeDev);
_transferToken(_tournament.feeToken, royaltyAddrFlp, _feeFlp);
_transferToken(_tournament.feeToken, _tournament.organizer, _feeOrg);
}
emit UnlockFee(_tournamentId, _tournament.feeBalance);
}
function _EndedUnlockPrize(uint _tournamentId, address[] memory _winner) internal {
Tournament storage _tournament = tournamentMapping[_tournamentId];
_tournament.tournamentEnded = true;
uint256[] memory _prizeAmountArray = _tournament.prizeAmountArray;
require(_winner.length == _prizeAmountArray.length, "Arrays must be the same length.");
for (uint256 i = 0; i < _winner.length; i++) {
uint256 _prizeAmount = _prizeAmountArray[i];
if (_prizeAmount > 0) {
uint256 _prizeDev = (_prizeAmount * RoyaltyPrizeDev) / 100;
uint256 _prizeFlp = (_prizeAmount * RoyaltyPrizeFlp) / 100;
uint256 _prizeUser = _prizeAmount - (_prizeDev + _prizeFlp);
if (_tournament.referees.length > 0 && _tournament.referees[0] != address(0)) {
uint256 _totalRefereePrize = (_prizeAmount * RoyaltyPrizeReferee) / 100;
uint256 _prizePerReferee = _totalRefereePrize / _tournament.referees.length;
for (uint256 j = 0; j < _tournament.referees.length; j++) {
_transferToken(_tournament.prizeToken, _tournament.referees[j], _prizePerReferee);
}
_prizeUser -= _totalRefereePrize;
}
_transferToken(_tournament.prizeToken, royaltyAddrDev, _prizeDev);
_transferToken(_tournament.prizeToken, royaltyAddrFlp, _prizeFlp);
_transferToken(_tournament.prizeToken, _winner[i], _prizeUser);
}
}
emit UnlockPrize(_tournamentId, _tournament.prizeAmount);
}
function _CanceledUnlockTransfer(uint _tournamentId, address[] memory _players) internal {
Tournament storage _tournament = tournamentMapping[_tournamentId];
_tournament.tournamentCanceled = true;
if(_tournament.joinFee > 0){
for (uint256 i = 0; i < _players.length; i++) {
_tournament.feeToken.transfer(_players[i], _tournament.joinFee);
}
}
if(_tournament.isFunding){
Funding storage funding = fundingMapping[_tournamentId];
funding.fundingActive = false;
funding.fundingCanceled = true;
for (uint i = 0; i < funding.contributors.length; i++) {
address contributor = funding.contributors[i];
uint256 amount = funding.contributions[contributor];
funding.fundingToken.transfer(contributor, amount);
}
}else{
if(_tournament.prizeAmount > 0){
_tournament.prizeToken.transfer(_tournament.organizer, _tournament.prizeAmount);
}
}
}
function _transferToken(IERC20 token, address to, uint256 amount) internal {
if (amount > 0) {
require(token.transfer(to, amount),"Transfer failed");
}
}
function setRoyaltyDevAddress(address _royaltyAddr) external onlyRole(DEFAULT_ADMIN_ROLE){
royaltyAddrDev = _royaltyAddr;
}
function setRoyaltyFlpAddress(address _royaltyAddr) external onlyRole(DEFAULT_ADMIN_ROLE){
royaltyAddrFlp = _royaltyAddr;
}
function setPrizeRoyaltyDevRate(uint _royaltyRate) external onlyRole(DEFAULT_ADMIN_ROLE){
RoyaltyPrizeDev = _royaltyRate;
}
function setPrizeRoyaltyFlpRate(uint _royaltyRate) external onlyRole(DEFAULT_ADMIN_ROLE){
RoyaltyPrizeFlp = _royaltyRate;
}
function setPrizeRoyaltyRefRate(uint _royaltyRate) external onlyRole(DEFAULT_ADMIN_ROLE){
RoyaltyPrizeReferee = _royaltyRate;
}
function setRegfeeRoyaltyDevRate(uint _royaltyRate) external onlyRole(DEFAULT_ADMIN_ROLE){
RoyaltyRegfeeDev = _royaltyRate;
}
function setRegfeeRoyaltyFlpRate(uint _royaltyRate) external onlyRole(DEFAULT_ADMIN_ROLE){
RoyaltyRegfeeFlp = _royaltyRate;
}
function setRegfeeRoyaltyRefRate(uint _royaltyRate) external onlyRole(DEFAULT_ADMIN_ROLE){
RoyaltyRegfeeReferee = _royaltyRate;
}
function setMinimumFundingRate(uint _newRate) external onlyRole(DEFAULT_ADMIN_ROLE) {
require(_newRate > 0 && _newRate <= 100, "Invalid rate");
minFundingRate = _newRate;
}
function getFundingProgress(uint _tournamentId) public view returns (uint) {
Funding storage funding = fundingMapping[_tournamentId];
if (funding.fundingGoal == 0) {
return 0;
}
uint progress = (funding.totalFunded * 100) / funding.fundingGoal;
return progress;
}
function getMinFundingRate() public view returns (uint) {
return minFundingRate;
}
function getFundingDetails(uint _tournamentId) public view returns (uint256 startTime, uint256 endTime, address fundingToken, uint256 totalFunded, uint256 fundingGoal, bool fundingActive, bool fundingEnded, bool fundingCanceled, address[] memory contributors) {
Funding storage funding = fundingMapping[_tournamentId];
return (funding.startTime, funding.endTime, address(funding.fundingToken), funding.totalFunded, funding.fundingGoal, funding.fundingActive, funding.fundingEnded, funding.fundingCanceled, funding.contributors);
}
function isFundingSuccess(uint _tournamentId) public view returns (bool) {
uint progress = getFundingProgress(_tournamentId);
uint minRate = getMinFundingRate();
return progress >= minRate;
}
function getReferees(uint _tournamentId) public view returns (address[] memory referees) {
Tournament storage _tournament = tournamentMapping[_tournamentId];
return _tournament.referees;
}
function getTotalUserStakedAmount(address user) public view returns (uint256 totalAmount) {
totalAmount = 0;
for (uint i = 0; i < stakingContracts.length; i++) {
(uint256 amount,,) = stakingContracts[i].stakings(user);
totalAmount += amount;
}
}
function isSponsor(address user) public view returns (bool isSponsorRole) {
return hasRole(FACTORY_ROLE, user);
}
function calculateMaxFundingLimit(uint256 stakedNFTs) public view returns (uint256) {
uint256 maxStakedNFTs = 50;
if (stakedNFTs <= 1) {
return baseLimit;
}
if (stakedNFTs > maxStakedNFTs) {
stakedNFTs = maxStakedNFTs;
}
return baseLimit * stakedNFTs;
}
}
文件 10 的 14:Miracle-Fundable-Tournament.sol
pragma solidity ^0.8.22;
import "./Miracle-Fundable-Escrow.sol";
import "@thirdweb-dev/contracts/extension/PermissionsEnumerable.sol";
import "@thirdweb-dev/contracts/extension/Multicall.sol";
import "@thirdweb-dev/contracts/extension/ContractMetadata.sol";
contract FundableTournament is PermissionsEnumerable, Multicall, ContractMetadata {
address public deployer;
address payable public EscrowAddr;
uint[] private OnGoingTournaments;
uint[] private EndedTournaments;
uint[] public mvpMintAmount;
uint[] public bptMintAmount;
IMintableERC20 VoteToken;
IMintableERC20 BattlePoint;
uint public minTournamentRate;
struct Tournament {
bool created;
bool isFunding;
bool isSponsorTournament;
address [] players;
mapping(address => bool) playerRegistered;
address [] ranker;
address organizer;
uint PlayersLimit;
uint registerStartTime;
uint registerEndTime;
uint prizeCount;
bool tournamentEnded;
string scoreURI;
}
mapping(uint => Tournament) public tournamentMapping;
event NewPersonalRecord(uint tournamentId, address account, uint score);
event ScoreUpdated(uint tournamentId, string uri);
event ShuffledPlayers(uint tournamentId, uint playersCount);
bytes32 public constant ESCROW_ROLE = keccak256("ESCROW_ROLE");
bytes32 public constant FACTORY_ROLE = keccak256("FACTORY_ROLE");
constructor(address _VoteToken, address _BattlePoint, string memory _contractURI) {
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setupRole(FACTORY_ROLE, msg.sender);
_setupRole(FACTORY_ROLE, 0x2fB586cD6bF507998e0816897D812d5dF2aF7677);
_setupRole(FACTORY_ROLE, 0x7C7f65a0f86a556aAA04FD9ceDb1AA6D943C35c3);
_setupRole(FACTORY_ROLE, 0xd278a5A5B9A83574852d25F08420029972fd2c6f);
_setupRole(FACTORY_ROLE, 0x7c35582e6b953b0D7980ED3444363B5c99d1ded3);
_setupRole(FACTORY_ROLE, 0xe463D4fdBc692D9016949881E6a5e18d815C4537);
_setupRole(FACTORY_ROLE, 0x622DfbD67fa2e87aa8c774e14fda2791656f282b);
_setupRole(FACTORY_ROLE, 0xbE810123C22046d93Afb018d7c4b7248df0088BE);
_setupRole(FACTORY_ROLE, 0xc184A36eac1EA5d62829cc80e8e57E7c4994D40B);
_setupRole(FACTORY_ROLE, 0xDCa74207a0cB028A2dE3aEeDdC7A9Be52109a785);
_setupRole(FACTORY_ROLE, 0x2D328292CDfA09e4Aa247F45753A13e546cEB29B);
_setupRole(FACTORY_ROLE, 0x8914b41C3D0491E751d4eA3EbfC04c42D7275A75);
_setupRole(FACTORY_ROLE, 0xe818aa4d851645aB525da5C11Ac231e2fAEDA322);
_setupRole(FACTORY_ROLE, 0x116CAceb39AEA14BC93EF7f67f9176A32470F073);
_setupRole(FACTORY_ROLE, 0xC498f5e9cba0637De9A3d59FBc113286230E7EB2);
_setupRole(FACTORY_ROLE, 0x7a43acBA2D4C5ECe3A3114b48d22e6aedce72890);
_setupRole(FACTORY_ROLE, 0x0ea564b0119555B14e96327A9ea8463bCCC39291);
_setupRole(FACTORY_ROLE, 0x2ABc2dB509B7519b018FCf3194906a89c0aa127e);
_setupRole(FACTORY_ROLE, 0x6C5d470a4777A81655Cb220dC5C8c6B38D2DF257);
_setupRole(FACTORY_ROLE, 0xA49DF5b16422cc2afee9eeEe3f161e1e035C3C91);
VoteToken = IMintableERC20(_VoteToken);
BattlePoint = IMintableERC20(_BattlePoint);
mvpMintAmount = [10000000000000000000,5000000000000000000,3000000000000000000,1000000000000000000];
bptMintAmount = [100000000000000000000,50000000000000000000,10000000000000000000];
minTournamentRate = 100;
deployer = msg.sender;
_setupContractURI(_contractURI);
}
function _canSetContractURI() internal view virtual override returns (bool){
return msg.sender == deployer;
}
modifier registrationOpen(uint tournamentId) {
Tournament storage tournament = tournamentMapping[tournamentId];
require(block.timestamp >= tournament.registerStartTime, "Registration has not started yet");
require(block.timestamp <= tournament.registerEndTime, "Registration deadline passed");
_;
}
function connectEscrow(address payable _escrowAddr) public onlyRole(DEFAULT_ADMIN_ROLE) {
_setupRole(ESCROW_ROLE, _escrowAddr);
EscrowAddr = _escrowAddr;
}
function createTournament(uint _tournamentId, bool _isFunding, bool _isSponsorTournament, address _organizer, uint _registerStartTime, uint _registerEndTime, uint _prizeCount, uint _playerLimit) public onlyRole(ESCROW_ROLE) {
Tournament storage newTournament = tournamentMapping[_tournamentId];
newTournament.created = true;
newTournament.isSponsorTournament = _isSponsorTournament;
newTournament.isFunding = _isFunding;
newTournament.organizer = _organizer;
newTournament.registerStartTime = _registerStartTime;
newTournament.registerEndTime = _registerEndTime;
newTournament.prizeCount = _prizeCount;
newTournament.PlayersLimit = _playerLimit;
newTournament.tournamentEnded = false;
addOnGoingTournament(_tournamentId);
}
function register(uint _tournamentId, address _player) public registrationOpen(_tournamentId) onlyRole(ESCROW_ROLE){
require(block.timestamp > tournamentMapping[_tournamentId].registerStartTime, "Registration has not started yet");
require(block.timestamp < tournamentMapping[_tournamentId].registerEndTime, "Registration deadline passed");
require(!tournamentMapping[_tournamentId].playerRegistered[_player], "Address already registered");
require(tournamentMapping[_tournamentId].players.length < tournamentMapping[_tournamentId].PlayersLimit, "Tournament is full.");
tournamentMapping[_tournamentId].playerRegistered[_player] = true;
tournamentMapping[_tournamentId].players.push(_player);
}
function kickPlayer(uint _tournamentId, address _player) public onlyRole(FACTORY_ROLE){
require(tournamentMapping[_tournamentId].playerRegistered[_player] == true, "Player not registered");
uint length = tournamentMapping[_tournamentId].players.length;
for (uint i = 0; i < length; i++) {
if (tournamentMapping[_tournamentId].players[i] == _player) {
tournamentMapping[_tournamentId].players[i] = tournamentMapping[_tournamentId].players[length - 1];
tournamentMapping[_tournamentId].players.pop();
break;
}
}
tournamentMapping[_tournamentId].playerRegistered[_player] = false;
}
function kickPlayerBatch(uint _tournamentId, address[] memory _players) external onlyRole(FACTORY_ROLE) {
require(_players.length > 0, "No players to kick");
for (uint j = 0; j < _players.length; j++) {
if (tournamentMapping[_tournamentId].playerRegistered[_players[j]]) {
uint length = tournamentMapping[_tournamentId].players.length;
for (uint i = 0; i < length; i++) {
if (tournamentMapping[_tournamentId].players[i] == _players[j]) {
tournamentMapping[_tournamentId].players[i] = tournamentMapping[_tournamentId].players[length - 1];
tournamentMapping[_tournamentId].players.pop();
break;
}
}
tournamentMapping[_tournamentId].playerRegistered[_players[j]] = false;
}
}
}
function updateScore(uint tournamentId, string calldata _uri) external onlyRole(FACTORY_ROLE) {
tournamentMapping[tournamentId].scoreURI = _uri;
}
function playersShuffle(uint tournamentId) public onlyRole(FACTORY_ROLE){
Tournament storage tournament = tournamentMapping[tournamentId];
address[] memory shuffledArray = tournament.players;
uint n = shuffledArray.length;
for (uint i = 0; i < n; i++) {
uint j = i + uint(keccak256(abi.encodePacked(block.timestamp))) % (n - i);
(shuffledArray[i], shuffledArray[j]) = (shuffledArray[j], shuffledArray[i]);
}
tournament.players = shuffledArray;
emit ShuffledPlayers(tournamentId, shuffledArray.length);
}
function endFunding(uint _tournamentId) external onlyRole(FACTORY_ROLE) {
FundableTournamentEscrow(EscrowAddr).endFunding(_tournamentId);
}
function cancelFunding(uint _tournamentId) external onlyRole(FACTORY_ROLE) {
FundableTournamentEscrow(EscrowAddr).cancelFunding(_tournamentId);
}
function endTournament(uint _tournamentId, address[] calldata _rankers) public onlyRole(FACTORY_ROLE) {
Tournament storage _tournament = tournamentMapping[_tournamentId];
require(!_tournament.tournamentEnded, "Tournament has already ended");
uint _prizeCount = _tournament.prizeCount;
address[] memory prizeAddr = new address[](_prizeCount);
for(uint i = 0; i < _prizeCount; i++){
prizeAddr[i] = _rankers[i];
}
if(_tournament.isSponsorTournament){
_mintVoteToken(_tournamentId, _rankers);
_mintBattlePoint(_tournamentId, _rankers);
}
FundableTournamentEscrow(EscrowAddr).endedTournament(_tournamentId, prizeAddr);
_tournament.tournamentEnded = true;
removeOnGoingTournament(_tournamentId);
addEndedTournament(_tournamentId);
}
function cancelTournament(uint _tournamentId) public onlyRole(FACTORY_ROLE) {
Tournament storage _tournament = tournamentMapping[_tournamentId];
require(!_tournament.tournamentEnded, "Tournament has already ended");
address[] memory _entryPlayers = _tournament.players;
FundableTournamentEscrow(EscrowAddr).canceledTournament(_tournamentId, _entryPlayers);
_tournament.tournamentEnded = true;
removeOnGoingTournament(_tournamentId);
addEndedTournament(_tournamentId);
}
function _mintVoteToken(uint _tournamentId, address[] calldata _rankers) internal {
Tournament storage _tournament = tournamentMapping[_tournamentId];
address[] memory _entryPlayers = _tournament.players;
for (uint i = 0; i < _rankers.length; i++) {
uint mintAmount = (i < mvpMintAmount.length) ? mvpMintAmount[i] : mvpMintAmount[mvpMintAmount.length - 1];
VoteToken.mintTo(_rankers[i], mintAmount);
}
for (uint j = 0; j < _entryPlayers.length; j++) {
if (!_isRanker(_entryPlayers[j], _rankers)) {
VoteToken.mintTo(_entryPlayers[j], mvpMintAmount[mvpMintAmount.length - 1]);
}
}
}
function _mintBattlePoint(uint _tournamentId, address[] calldata _rankers) internal {
Tournament storage _tournament = tournamentMapping[_tournamentId];
address[] memory _entryPlayers = _tournament.players;
for (uint i = 0; i < _rankers.length; i++) {
uint mintAmount = (i < bptMintAmount.length) ? bptMintAmount[i] : bptMintAmount[bptMintAmount.length - 1];
BattlePoint.mintTo(_rankers[i], mintAmount);
}
for (uint j = 0; j < _entryPlayers.length; j++) {
if (!_isRanker(_entryPlayers[j], _rankers)) {
uint mintAmount = bptMintAmount[bptMintAmount.length - 1];
if (mintAmount>0){
BattlePoint.mintTo(_entryPlayers[j], bptMintAmount[bptMintAmount.length - 1]);
}
}
}
}
function _isRanker(address player, address[] memory rankers) internal pure returns (bool) {
for (uint i = 0; i < rankers.length; i++) {
if (player == rankers[i]) {
return true;
}
}
return false;
}
function addOnGoingTournament(uint _tournamentId) internal {
OnGoingTournaments.push(_tournamentId);
}
function addEndedTournament(uint _tournamentId) internal {
EndedTournaments.push(_tournamentId);
}
function removeOnGoingTournament(uint _tournamentId) internal {
for (uint256 i = 0; i < OnGoingTournaments.length; i++) {
if (OnGoingTournaments[i] == _tournamentId) {
if (i != OnGoingTournaments.length - 1) {
OnGoingTournaments[i] = OnGoingTournaments[OnGoingTournaments.length - 1];
}
OnGoingTournaments.pop();
break;
}
}
}
function updateMvpMintAmount(uint[] calldata newMvpMintAmount) external onlyRole(DEFAULT_ADMIN_ROLE) {
mvpMintAmount = newMvpMintAmount;
}
function updateBptMintAmount(uint[] calldata newBptMintAmount) external onlyRole(DEFAULT_ADMIN_ROLE) {
bptMintAmount = newBptMintAmount;
}
function setVoteToken(IMintableERC20 _newVoteToken) external onlyRole(DEFAULT_ADMIN_ROLE) {
VoteToken = _newVoteToken;
}
function setBattlePoint(IMintableERC20 _newBattlePoint) external onlyRole(DEFAULT_ADMIN_ROLE) {
BattlePoint = _newBattlePoint;
}
function getRegistProgress(uint _tournamentId) public view returns (uint) {
Tournament storage _tournament = tournamentMapping[_tournamentId];
if (_tournament.PlayersLimit == 0) {
return 0;
}
uint progress = (_tournament.players.length * 100) / _tournament.PlayersLimit;
return progress;
}
function getMinTournamentRate() public view returns (uint) {
return minTournamentRate;
}
function isTounamentSuccess(uint _tournamentId) public view returns (bool) {
uint progress = getFundingProgress(_tournamentId);
uint minRate = getMinTournamentRate();
return progress >= minRate;
}
function isFundingSuccess(uint _tournamentId) public view returns (bool) {
return FundableTournamentEscrow(EscrowAddr).isFundingSuccess(_tournamentId);
}
function getAllTournamentCount() external view returns (uint) {
uint count = OnGoingTournaments.length + EndedTournaments.length;
return count;
}
function getOnGoingTournamentsCount() external view returns (uint) {
return OnGoingTournaments.length;
}
function getEndedTournamentsCount() external view returns (uint) {
return EndedTournaments.length;
}
function getOnGoingTournaments() external view returns (uint[] memory) {
return OnGoingTournaments;
}
function getEndedTournaments() external view returns (uint[] memory) {
return EndedTournaments;
}
function getPlayerCount(uint _tournamentId) external view returns(uint _playerCnt){
Tournament storage _tournament = tournamentMapping[_tournamentId];
return _tournament.players.length;
}
function getPlayers(uint _tournamentId) external view returns(address[] memory){
Tournament storage _tournament = tournamentMapping[_tournamentId];
return _tournament.players;
}
function getFundingProgress(uint _tournamentId) public view returns (uint) {
return FundableTournamentEscrow(EscrowAddr).getFundingProgress(_tournamentId);
}
}
文件 11 的 14:Multicall.sol
pragma solidity ^0.8.0;
import "../lib/Address.sol";
import "./interface/IMulticall.sol";
contract Multicall is IMulticall {
function multicall(bytes[] calldata data) external returns (bytes[] memory results) {
results = new bytes[](data.length);
address sender = _msgSender();
bool isForwarder = msg.sender != sender;
for (uint256 i = 0; i < data.length; i++) {
if (isForwarder) {
results[i] = Address.functionDelegateCall(address(this), abi.encodePacked(data[i], sender));
} else {
results[i] = Address.functionDelegateCall(address(this), data[i]);
}
}
return results;
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
}
文件 12 的 14:Permissions.sol
pragma solidity ^0.8.0;
import "./interface/IPermissions.sol";
import "../lib/Strings.sol";
contract Permissions is IPermissions {
error PermissionsUnauthorizedAccount(address account, bytes32 neededRole);
error PermissionsAlreadyGranted(address account, bytes32 role);
error PermissionsInvalidPermission(address expected, address actual);
mapping(bytes32 => mapping(address => bool)) private _hasRole;
mapping(bytes32 => bytes32) private _getRoleAdmin;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
modifier onlyRole(bytes32 role) {
_checkRole(role, msg.sender);
_;
}
function hasRole(bytes32 role, address account) public view override returns (bool) {
return _hasRole[role][account];
}
function hasRoleWithSwitch(bytes32 role, address account) public view returns (bool) {
if (!_hasRole[role][address(0)]) {
return _hasRole[role][account];
}
return true;
}
function getRoleAdmin(bytes32 role) external view override returns (bytes32) {
return _getRoleAdmin[role];
}
function grantRole(bytes32 role, address account) public virtual override {
_checkRole(_getRoleAdmin[role], msg.sender);
if (_hasRole[role][account]) {
revert PermissionsAlreadyGranted(account, role);
}
_setupRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual override {
_checkRole(_getRoleAdmin[role], msg.sender);
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address account) public virtual override {
if (msg.sender != account) {
revert PermissionsInvalidPermission(msg.sender, account);
}
_revokeRole(role, account);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = _getRoleAdmin[role];
_getRoleAdmin[role] = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
function _setupRole(bytes32 role, address account) internal virtual {
_hasRole[role][account] = true;
emit RoleGranted(role, account, msg.sender);
}
function _revokeRole(bytes32 role, address account) internal virtual {
_checkRole(role, account);
delete _hasRole[role][account];
emit RoleRevoked(role, account, msg.sender);
}
function _checkRole(bytes32 role, address account) internal view virtual {
if (!_hasRole[role][account]) {
revert PermissionsUnauthorizedAccount(account, role);
}
}
function _checkRoleWithSwitch(bytes32 role, address account) internal view virtual {
if (!hasRoleWithSwitch(role, account)) {
revert PermissionsUnauthorizedAccount(account, role);
}
}
}
文件 13 的 14:PermissionsEnumerable.sol
pragma solidity ^0.8.0;
import "./interface/IPermissionsEnumerable.sol";
import "./Permissions.sol";
contract PermissionsEnumerable is IPermissionsEnumerable, Permissions {
struct RoleMembers {
uint256 index;
mapping(uint256 => address) members;
mapping(address => uint256) indexOf;
}
mapping(bytes32 => RoleMembers) private roleMembers;
function getRoleMember(bytes32 role, uint256 index) external view override returns (address member) {
uint256 currentIndex = roleMembers[role].index;
uint256 check;
for (uint256 i = 0; i < currentIndex; i += 1) {
if (roleMembers[role].members[i] != address(0)) {
if (check == index) {
member = roleMembers[role].members[i];
return member;
}
check += 1;
} else if (hasRole(role, address(0)) && i == roleMembers[role].indexOf[address(0)]) {
check += 1;
}
}
}
function getRoleMemberCount(bytes32 role) external view override returns (uint256 count) {
uint256 currentIndex = roleMembers[role].index;
for (uint256 i = 0; i < currentIndex; i += 1) {
if (roleMembers[role].members[i] != address(0)) {
count += 1;
}
}
if (hasRole(role, address(0))) {
count += 1;
}
}
function _revokeRole(bytes32 role, address account) internal override {
super._revokeRole(role, account);
_removeMember(role, account);
}
function _setupRole(bytes32 role, address account) internal override {
super._setupRole(role, account);
_addMember(role, account);
}
function _addMember(bytes32 role, address account) internal {
uint256 idx = roleMembers[role].index;
roleMembers[role].index += 1;
roleMembers[role].members[idx] = account;
roleMembers[role].indexOf[account] = idx;
}
function _removeMember(bytes32 role, address account) internal {
uint256 idx = roleMembers[role].indexOf[account];
delete roleMembers[role].members[idx];
delete roleMembers[role].indexOf[account];
}
}
文件 14 的 14:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
function toHexStringChecksummed(address value) internal pure returns (string memory str) {
str = toHexString(value);
assembly {
let mask := shl(6, div(not(0), 255))
let o := add(str, 0x22)
let hashed := and(keccak256(o, 40), mul(34, mask))
let t := shl(240, 136)
for {
let i := 0
} 1 {
} {
mstore(add(i, i), mul(t, byte(i, hashed)))
i := add(i, 1)
if eq(i, 20) {
break
}
}
mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask)))))
o := add(o, 0x20)
mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask)))))
}
}
function toHexString(address value) internal pure returns (string memory str) {
str = toHexStringNoPrefix(value);
assembly {
let strLength := add(mload(str), 2)
mstore(str, 0x3078)
str := sub(str, 2)
mstore(str, strLength)
}
}
function toHexStringNoPrefix(address value) internal pure returns (string memory str) {
assembly {
str := mload(0x40)
mstore(0x40, add(str, 0x80))
mstore(0x0f, 0x30313233343536373839616263646566)
str := add(str, 2)
mstore(str, 40)
let o := add(str, 0x20)
mstore(add(o, 40), 0)
value := shl(96, value)
for {
let i := 0
} 1 {
} {
let p := add(o, add(i, i))
let temp := byte(i, value)
mstore8(add(p, 1), mload(and(temp, 15)))
mstore8(p, mload(shr(4, temp)))
i := add(i, 1)
if eq(i, 20) {
break
}
}
}
}
function toHexString(bytes memory raw) internal pure returns (string memory str) {
str = toHexStringNoPrefix(raw);
assembly {
let strLength := add(mload(str), 2)
mstore(str, 0x3078)
str := sub(str, 2)
mstore(str, strLength)
}
}
function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory str) {
assembly {
let length := mload(raw)
str := add(mload(0x40), 2)
mstore(str, add(length, length))
mstore(0x0f, 0x30313233343536373839616263646566)
let o := add(str, 0x20)
let end := add(raw, length)
for {
} iszero(eq(raw, end)) {
} {
raw := add(raw, 1)
mstore8(add(o, 1), mload(and(mload(raw), 15)))
mstore8(o, mload(and(shr(4, mload(raw)), 15)))
o := add(o, 2)
}
mstore(o, 0)
mstore(0x40, add(o, 0x20))
}
}
}
{
"compilationTarget": {
"contract/Miracle-Tournament-Release/Miracle-Fundable-Escrow.sol": "FundableTournamentEscrow"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 100
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_royaltyAddrDev","type":"address"},{"internalType":"address","name":"_royaltyAddrFlp","type":"address"},{"internalType":"address[]","name":"_stakingContractAddresses","type":"address[]"},{"internalType":"address","name":"_assetMasterAddr","type":"address"},{"internalType":"address","name":"_miracletournament","type":"address"},{"internalType":"address","name":"_miraclePass","type":"address"},{"internalType":"string","name":"_contractURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ContractMetadataUnauthorized","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"PermissionsAlreadyGranted","type":"error"},{"inputs":[{"internalType":"address","name":"expected","type":"address"},{"internalType":"address","name":"actual","type":"address"}],"name":"PermissionsInvalidPermission","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"PermissionsUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"prevURI","type":"string"},{"indexed":false,"internalType":"string","name":"newURI","type":"string"}],"name":"ContractURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tournamentId","type":"uint256"},{"indexed":false,"internalType":"address","name":"organizer","type":"address"}],"name":"EscrowCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tournamentId","type":"uint256"},{"indexed":false,"internalType":"address","name":"fundingUser","type":"address"},{"indexed":false,"internalType":"uint256","name":"fundingAmount","type":"uint256"}],"name":"Fund","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tournamentId","type":"uint256"}],"name":"FundCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tournamentId","type":"uint256"}],"name":"FundEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tournamentId","type":"uint256"},{"indexed":false,"internalType":"address","name":"user","type":"address"}],"name":"KickPlayer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tournamentId","type":"uint256"},{"indexed":false,"internalType":"address","name":"user","type":"address"}],"name":"Registration","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tournamentId","type":"uint256"}],"name":"TournamentCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tournamentId","type":"uint256"}],"name":"TournamentEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tournamentId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UnlockFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tournamentId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UnlockPrize","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FACTORY_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RoyaltyPrizeDev","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RoyaltyPrizeFlp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RoyaltyPrizeReferee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RoyaltyRegfeeDev","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RoyaltyRegfeeFlp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RoyaltyRegfeeReferee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOURNAMENT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetMasterAddr","outputs":[{"internalType":"contract AssetMaster","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"stakedNFTs","type":"uint256"}],"name":"calculateMaxFundingLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tournamentId","type":"uint256"}],"name":"cancelFunding","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tournamentId","type":"uint256"},{"internalType":"address[]","name":"_entryPlayers","type":"address[]"}],"name":"canceledTournament","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_assetMasterAddr","type":"address"}],"name":"connectAssestMaster","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_stakingContractAddresses","type":"address[]"}],"name":"connectEditionStakings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_miraclePassAddr","type":"address"}],"name":"connectMiraclePass","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_miracletournament","type":"address"}],"name":"connectTournament","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tournamentInfo","type":"uint256[]"},{"internalType":"bool","name":"_isFunding","type":"bool"},{"internalType":"address[]","name":"_prizeFeeToken","type":"address[]"},{"internalType":"uint256[]","name":"_prizeFeeAmount","type":"uint256[]"},{"internalType":"uint256[]","name":"_regStartEndTime","type":"uint256[]"},{"internalType":"uint256[]","name":"_FundStartEndTime","type":"uint256[]"},{"internalType":"uint256[]","name":"_prizeAmountArray","type":"uint256[]"},{"internalType":"string","name":"_tournamentURI","type":"string"},{"internalType":"uint256","name":"_playerLimit","type":"uint256"},{"internalType":"address[]","name":"_referees","type":"address[]"}],"name":"createTournamentEscrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deployer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tournamentId","type":"uint256"}],"name":"endFunding","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tournamentId","type":"uint256"},{"internalType":"address[]","name":"_withdrawAddresses","type":"address[]"}],"name":"endedTournament","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tournamentId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"fundTournament","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"fundingMapping","outputs":[{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"contract IERC20","name":"fundingToken","type":"address"},{"internalType":"uint256","name":"totalFunded","type":"uint256"},{"internalType":"uint256","name":"fundingGoal","type":"uint256"},{"internalType":"bool","name":"fundingActive","type":"bool"},{"internalType":"bool","name":"fundingEnded","type":"bool"},{"internalType":"bool","name":"fundingCanceled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tournamentId","type":"uint256"}],"name":"getFundingDetails","outputs":[{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"address","name":"fundingToken","type":"address"},{"internalType":"uint256","name":"totalFunded","type":"uint256"},{"internalType":"uint256","name":"fundingGoal","type":"uint256"},{"internalType":"bool","name":"fundingActive","type":"bool"},{"internalType":"bool","name":"fundingEnded","type":"bool"},{"internalType":"bool","name":"fundingCanceled","type":"bool"},{"internalType":"address[]","name":"contributors","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tournamentId","type":"uint256"}],"name":"getFundingProgress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinFundingRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tournamentId","type":"uint256"}],"name":"getReferees","outputs":[{"internalType":"address[]","name":"referees","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"member","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getTotalUserStakedAmount","outputs":[{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRoleWithSwitch","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tournamentId","type":"uint256"}],"name":"isFundingSuccess","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"isSponsor","outputs":[{"internalType":"bool","name":"isSponsorRole","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tournamentId","type":"uint256"},{"internalType":"address","name":"_player","type":"address"}],"name":"kickPlayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minFundingRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"miraclePass","outputs":[{"internalType":"contract iMiraclePass","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"miracletournament","outputs":[{"internalType":"contract FundableTournament","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tournamentId","type":"uint256"}],"name":"register","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"royaltyAddrDev","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"royaltyAddrFlp","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newRate","type":"uint256"}],"name":"setMinimumFundingRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_royaltyRate","type":"uint256"}],"name":"setPrizeRoyaltyDevRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_royaltyRate","type":"uint256"}],"name":"setPrizeRoyaltyFlpRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_royaltyRate","type":"uint256"}],"name":"setPrizeRoyaltyRefRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_royaltyRate","type":"uint256"}],"name":"setRegfeeRoyaltyDevRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_royaltyRate","type":"uint256"}],"name":"setRegfeeRoyaltyFlpRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_royaltyRate","type":"uint256"}],"name":"setRegfeeRoyaltyRefRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_royaltyAddr","type":"address"}],"name":"setRoyaltyDevAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_royaltyAddr","type":"address"}],"name":"setRoyaltyFlpAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakingContracts","outputs":[{"internalType":"contract IStakingContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gameTier","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"tierValify","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tournamentMapping","outputs":[{"internalType":"address","name":"organizer","type":"address"},{"internalType":"bool","name":"isFunding","type":"bool"},{"internalType":"bool","name":"isSponsored","type":"bool"},{"internalType":"uint256","name":"tier","type":"uint256"},{"internalType":"contract IERC20","name":"prizeToken","type":"address"},{"internalType":"contract IERC20","name":"feeToken","type":"address"},{"internalType":"uint256","name":"prizeAmount","type":"uint256"},{"internalType":"uint256","name":"joinFee","type":"uint256"},{"internalType":"uint256","name":"feeBalance","type":"uint256"},{"internalType":"bool","name":"tournamentCreated","type":"bool"},{"internalType":"bool","name":"tournamentEnded","type":"bool"},{"internalType":"bool","name":"tournamentCanceled","type":"bool"},{"internalType":"string","name":"tournamentURI","type":"string"},{"internalType":"uint256","name":"PlayersLimit","type":"uint256"}],"stateMutability":"view","type":"function"}]